这是我第一次冒险进入多线程,我想我错过了一些关键概念,所以任何帮助将不胜感激。我正在尝试为一个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