Hi!
Ich habe eine Klasse geschrieben, die es ermöglichen soll threadsafe in ein Logfile schreiben zu können. Nur bin ich mir nicht sicher, ob ich das alles richtig gemacht habe. Deswegen würde ich euch bitten, ein kleines "Review" über meine Klasse zu halten.
Kurze Erklärung: Ich benutze Queue um eine Warteschlange zu realisieren. Per Queue.Synchronize() erstelle ich einen Wrapper um die Warteschlange der sie threadsafe machen sollte. Jedesmal, wenn etwas geloggt werden soll, wird der Eintrag direkt ans Ende der Warteschlange geschrieben. Mit einem Timer der alle 100ms aufgerufen wird, laufe ich die gesamte Warteschlange durch und schreibe den gesamten Inhalt ins Logfile. Danach lösche ich den gesamten Inhalt der Warteschlange.
Ok hier nun der Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| public class LogFile { private string m_Filename = null; private Queue m_LogQueue = new Queue(); private Queue m_LogSyncQueue = null; private System.Timers.Timer m_LogFileWriterTimer = null; private const int LogFileWriterTimerIntervall = 100; public void LogFile(string Filename) { m_Filename = Filename; StreamWriter LogFile = new StreamWriter(m_Filename); LogFile.Close();
m_LogSyncQueue = Queue.Synchronized(m_LogQueue);
m_LogFileWriterTimer = new System.Timers.Timer(); m_LogFileWriterTimer.Elapsed += new ElapsedEventHandler(LogFileWriterTimerEvent); m_LogFileWriterTimer.Interval = LogFileWriterTimerIntervall; m_LogFileWriterTimer.Enabled = true; } ~LogFile() { m_LogFileWriterTimer.Enabled = false; }
public void Log(string msg) { m_LogSyncQueue.Enqueue(string.Format("{0}:{1}:{2}:{3} {4}\r\n", System.DateTime.Now.Hour, System.DateTime.Now.Minute, System.DateTime.Now.Second, System.DateTime.Now.Millisecond, msg); }
private void LogFileWriterTimerEvent(object sender, System.Timers.ElapsedEventArgs e) { StreamWriter LogFile = File.AppendText(m_Filename);
foreach(Object obj in m_LogSyncQueue) { LogFile.WriteLine(obj); } m_LogSyncQueue.Clear();
LogFile.Close(); } } |
Ich könnte mir vorstellen, dass es ein Problem gibt wenn genau zwischen dem Ende der foreach-Schleife und m_LogSyncQueue.Clear() aus dem Unterprogramm rausgesprungen wird (wegen eines anderen Threads) und dieser Thread nun Log() aufruft. Dann würde die Nachricht verloren gehen. Die Frage ist, ob dies überhaupt möglich ist?
Noch eine Frage nebenbei, gibt es eigentlich zwischen Threads und Timerevents einen unterschied in der Behandlung? Sprich: Müssen Methoden die in Timerevents aufgerufen werden auch threadsafe sein?
PS: Der Code wurde noch nicht getestet, ich wollte, dass er zuerst in der Theorie funktioniert.
Danke für eure Hilfe!
Moderiert von Christian S.: Code- durch C#-Tags ersetzt