이것은 멀티 스레딩에 대한 나의 첫 번째 모험이며 몇 가지 주요 개념을 놓치고 있다고 생각합니다. 그래서 어떤 도움을 주시면 감사하겠습니다. asp.net 응용 프로그램에 대한 로그 관리자를 만들려고합니다. 우리 시스템에서 많은 양의 데이터에 대해 조회/삽입/수정/삭제를 로깅합니다. 끊임없이 행을 삽입하는 대신, 메모리에 로그 항목 목록을 보유하는 싱글 톤을 생성하여 특정 크기에 도달 할 때까지 한 번에 모두 db에 기록하는 방법이라고 생각했습니다. 그런 다음 로그를 작성할 필요가있을 때 새 스레드에서이를 실행하면 성능이 향상 될 것이라고 생각했습니다. 아래는 나의 테스트 코드이다. 스레딩을 제거하면 DB에서 500 행을 얻을 수 있지만 멀티 스레딩을 사용하면 약 200-300이됩니다. 약 절반의 레코드가 삽입되지 않습니다. 이것이 멀티 스레딩에 유효한 용도인가요? 제가 뭘 잘못하고 있습니까? 고맙습니다.이 여러 가지 예에서 내가 뭘 잘못하고 있습니까?
LogManager의 :
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
'{throw (ex);/* KeepGoing * /}. '을 사용하지 마십시오. 그것은 스택을 엉망으로 만들고 여전히 예외를 처리해야합니다. –
실수로 던져 버렸습니다. 딸꾹질을 당하면 계속 가고 싶었어요. 너는 내가 모두 잡아 먹는 것을 제거해야한다고 말하는거야? – Mike