C# Multithreading und LogFile

Magic1416

Lieutenant
Registriert
Dez. 2003
Beiträge
513
Hi,

ich bin gerade am überlegen, wie man sinnvoll ein LogFile für Multithreading implementieren könnte. Das grundsätzliche Problem dabei ist, dass die vielen Threads halt völlig ungeordnet ins LogFile schreiben, was es unterm Strich dann unbrauchbar macht. Was ich suche, ist eine konzeptionelle Idee, wie sowas am besten umgesetzt werden könnte. Meine Idee ist bisher folgende:

Ich habe eine LogFile Klasse, welche die Methode WriteEntry2 bereitstellt.

Code:
object _lock = new object();
        private void WriteEntry2(string text,LogfileMessageType lmType)
        {
            lock (_lock)
            {
                using (FileStream fs = new FileStream(_logfile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                {
                    using (StreamWriter sw = new StreamWriter(fs))
                    {
                        if (text.Length > 0)
                            sw.WriteLine(string.Format("{0};{1};{2};{3}", GetTimeStamp(), GetThreadID(), lmType, text));
                        else
                            sw.WriteLine(string.Empty);
                    }
                }
            }
        }

Mein Konzept sieht vor, dass das LogFile durch die Threads geöffnet und geschlossen wird, sodass die Threads nicht gleichzeitig ins File schreiben. Das LogFile soll am besten in Excel betrachtet werden. Durch das Semicolon erhält man eine Datenstruktur. Man kann somit nach der Thread ID filtern.

Meine Frage ist, ob das Konzept im Hinblick auf die Performance und die Übersicht in Ordnung ist. Gibt es für den Schreibvorgang eventuell eine bessere Lösung als den Filestream und Streamwriter permanent zu öffnen und zu schließen. Man soll ja auch die Möglichkeit haben, das LogFile betrachten zu können, während noch was passiert.

Danke für Eure Anmerkungen
Gruß Magic
 
Locks auf Dateien sind eklig.

Schreib dir lieber einen Thread, der in das File schreibt, was ihm in eine thread safe Queue abgelegt wird von den unterschiedlichen worker threads.
 
Hallo Magic,

ohne mal das Konzept zu hinterfragen:
Wenn du die Daten sofort in der Datei lesbar haben willst, musst du nicht das Streamwriter Objekt schließen.
Es sollte reichen wenn du dies einbaust nach jedem
Code:
sw.WriteLine(string.Empty);

folgenden Code einfügst:
Code:
sw.Flush();

Damit wird der Cache des Streamwriter Objekts in die Datei geschrieben.

Quelle: Microsoft MSDN
 
Ich würde statt selber Loggings zu erstellen auf ein Framework zurückgreifen, welches auch Multithreading beherrscht. Empfehlung:
log4Net mit Common.Logging-Adapter. Gibts als Nuget-Packages aus der offiziellen Paketquelle. Tausend mal besser als eine eigene Variante zu schreiben.
 
BCBO1991 schrieb:
ohne mal das Konzept zu hinterfragen:
Wenn du die Daten sofort in der Datei lesbar haben willst, musst du nicht das Streamwriter Objekt schließen.
Es sollte reichen wenn du dies einbaust nach jedem

Es ist meine erste Idee. Sie funktioniert soweit ja auch. Durch den Thread erhoffe ich mir eine Ideale bzw. beste Lösung.
Also macht es mehr Sinn, folgendes zu machen:

Code:
FileStream _fs;
        StreamWriter _sw;
        private void openFile()
        {
            
           //Wird im Constructor ausgeführt
           _fs = new FileStream(_logfile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
            _sw = new StreamWriter(_fs);
        }

        private void closeFile()
        {
            
           //Wird im Destructor ausgeführt
           _sw.Close();
            _fs.Close();
        }


        object _lock = new object();
        private void WriteEntry2(string text,LogfileMessageType lmType)
        {
            lock (_lock)
            {
               
                if (text.Length > 0)
                    _sw.WriteLine(string.Format("{0};{1};{2};{3}", GetTimeStamp(), GetThreadID(), lmType, text));
                else
                    _sw.WriteLine(string.Empty);

                _sw.Flush();
               
            }
        }
 
Hi,

muss mich da Thaxll'ssillyia anschließen und fragen: warum erfindest du das Rad neu, wenn es fertige Frameworks gibt, die das schneller, sauberer und besser (und nebenbei auch noch getestet) machen? log4net ist sehr gut was das angeht.

VG,
Mad
 
Madman1209 schrieb:
Hi,

muss mich da Thaxll'ssillyia anschließen und fragen: warum erfindest du das Rad neu, wenn es fertige Frameworks gibt, die das schneller, sauberer und besser (und nebenbei auch noch getestet) machen? log4net ist sehr gut was das angeht.

VG,
Mad

Das liegt daran, weil ich das log4net noch nicht kannte. Ich habs mir gerade eben runtergeladen.
Ergänzung ()

the_nobs schrieb:
ähh...
file aufmachen und zumachen ist relativ dämlich (IMHO)
Vor allem weil sich die Threads sicher den Filehandle teilen. D.h. beide Threads können das file aufmachen und gleichzeitig reinschreiben.

warum nicht schon was existierendes nehmen
Z.B: http://logging.apache.org/log4net/
oder hier eine Übersicht
http://www.dotnetlogging.com/

Nur rein Interesse halber. Das Öffnen und Schließen des Files ist in Beispiel 2 von mir abgestellt. Vielleicht hattest Du den Post 5 noch nicht gelesen gehabt. Aber wie kommst Du darauf, dass mehrere Threads sich gleichzeitig am Filehandle bedienen können ? Ich habe doch nicht umsonst den Abschnitt

Code:
lock(_lock)
{
         ...
}

eingebaut gehabt. Schon im ersten Codebeispiel.
 
Magic1416 schrieb:
Nur rein Interesse halber. Das Öffnen und Schließen des Files ist in Beispiel 2 von mir abgestellt. Vielleicht hattest Du den Post 5 noch nicht gelesen gehabt. Aber wie kommst Du darauf, dass mehrere Threads sich gleichzeitig am Filehandle bedienen können ? Ich habe doch nicht umsonst den Abschnitt
Code:
lock(_lock)
{
         ...
}
eingebaut gehabt. Schon im ersten Codebeispiel.

Post 5 war noch nicht da wie ich geschrieben habe, deswegen wusste ich das noch nicht
bezüglich des codes: habe ich übersehen, bzw. ich habe das falsch verstanden.
also -> vergiss den ersten teil meines Postings und nimm eine bestehende Logging Bibliothek. in 99% der Fällen wirst du damit auskommen.
 
Zurück
Oben