這是我第一次冒險進入多線程,我想我錯過了一些關鍵概念,所以任何幫助將不勝感激。我正在嘗試爲一個asp.net應用程序創建一個日誌管理器。我們將在系統中的大量數據上記錄查看/插入/修改/刪除操作。而不是不斷地插入行,我認爲也許如果我創建了一個單例來保存內存中的日誌條目列表,直到它達到一定的大小,然後將它們全部寫入數據庫一次。然後我想,在日誌需要寫入時,在新的線程上運行它可以提高性能。以下是我的測試代碼。如果我刪除線程,我會得到數據庫中的500行,但是當我使用多線程時,我會獲得大約200-300。大約一半的記錄沒有被插入。這是多線程的有效用法,我做錯了什麼?謝謝。我在這個multitheading示例中做了什麼錯誤?
日誌管理:
public sealed class LogManager
{
private static LogManager _Log = null;
private static readonly object singletonLock = new object();
private static readonly object listLock = new object();
private List<LogEntry> LogEntries { get; set; }
public static LogManager Log
{
get
{
if (_Log == null)
{
lock (singletonLock)
{
if (_Log == null)
{
_Log = new LogManager();
}
}
}
return _Log;
}
}
public LogManager()
{
LogEntries = new List<LogEntry>();
}
public void Add(LogEntry logEntry)
{
lock (listLock)
{
LogEntries.Add(logEntry);
if (LogEntries.Count >= 100)
{
ThreadStart thread = delegate { Flush(new List<LogEntry>(LogEntries)); };
new Thread(thread).Start();
//Flush(LogEntries);
LogEntries.Clear();
}
}
}
private static void Flush(List<LogEntry> logEntries)
{
using (var conn = new SqlConnection(DAL.ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "spInsertLog";
conn.Open();
foreach (var logEntry in logEntries)
{
cmd.Parameters.AddWithValue("@ID", logEntry.ID);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex) { throw (ex);/*KeepGoing*/}
cmd.Parameters.Clear();
}
}
}
}
}
控制檯應用程序:
class Program
{
static void Main(string[] args)
{
var stopwatch = new Stopwatch();
for (int i = 0; i < 500; i++)
{
stopwatch.Start();
LogManager.Log.Add(new LogEntry() { ID = i });
Console.WriteLine(String.Format("Count: {0} Time: {1}",i.ToString(),stopwatch.ElapsedMilliseconds));
stopwatch.Stop();
stopwatch.Reset();
}
}
}
我的第一個猜測是,當循環停止時,你有許多日誌條目還沒有被刷新。 – RQDQ 2011-03-29 14:44:16
請勿使用{{throw(ex);/* KeepGoing * /}。它弄亂了你的堆棧,你仍然需要處理異常。 – 2011-03-29 14:44:28
我遺漏了(前)錯誤。我希望它繼續下去,如果它打嗝。你是說我應該刪除所有的嘗試? – Mike 2011-03-29 14:48:44