Laden...

In einem WindowsService kann die StreamWriter-Klasse nur einzelne Zeilen schreiben

Erstellt von AtHeOS vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.805 Views
A
AtHeOS Themenstarter:in
156 Beiträge seit 2005
vor 10 Jahren
In einem WindowsService kann die StreamWriter-Klasse nur einzelne Zeilen schreiben

Grüß euch,

das Thema beschäftigt mich jetzt wirklich schon lange und deswegen wende ich mich an euch.
Ich habe ein Programm das via Windows Forms und auch als Windows Service ausgeführt werden kann.
Wenn der Windows Service ausgeführt wird, dann funktioniert der StreamWriter mMn nicht wie erwartet.
Wenn ich z.B.

                                
using (file = new StreamWriter(this._LogPath + filename, true))
{
   file.WriteLine(FormatMessage);
}

schreibe, dann funktioniert das Ganze auch im WindowsService, da es möglich ist die Datei zu erstellen und auch EINE einzige Zeile darin zu schreiben. Somit ist es möglich Zeile für Zeile zu schreiben, was performanztechnisch relativ schlecht ist.
Wenn ich jetzt WriteLine mehrfach hintereinander aufrufe ODER mit einem StringBuilder mehrere Zeilen gleichzeitig in die Datei schreiben möchte, erhalte ich laut ProcMon eine SharingViolation.

Generell wird bei diesem Problem immer von einem Berechtigungsproblem gesprochen. Ich habe jetzt aber auch einen eigenen Administrator angelegt unter dem der Dienst läuft(nur testweise) der auch volle Rechte auch den Zielordner hat und trotzdem bleibt das Verhalten gleich. Als WindowsForms tritt dieses Problem nicht auf.(.NET Framework 4)
Das Komische dabei ist, es ist möglich die Datei anzulegen und jeweils pro neuer StreamWriter-Instanz eine Zeile darin zu schreiben.

Dnake für eure Hilfe.

lg atheos

16.806 Beiträge seit 2008
vor 10 Jahren

Du solltest in diesen Fällen die Logs zwischenspeichern und im Intervall den Cache in eine Datei übertragen.
Sowas ist deutlich Prozesssicherer und dazu auch noch performanter.

Schau Dir mal zB NLog an; das funktioniert auch nach diesem Prinzip.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo AtHeOS,

mit einem StringBuilder mehrere Zeilen gleichzeitig in die Datei schreiben

ich kann mir nicht vorstellen, dass es bei einem Text (einer bestimmten Länge) einen Unterschied macht, wieviele Zeilenvorschübe darin enthalten sind.

Wenn file.WriteLine("xyz") klappt, dann sollte auch file.WriteLine("x\nz") und file.WriteLine("\n\n\n") klappen.

herbivore

A
AtHeOS Themenstarter:in
156 Beiträge seit 2005
vor 10 Jahren

Grüß euch,

danke für eure Antworten.
@herbivore: das würde ich auch so sehen, deswegen verstehe ich das Problem nicht.
Bei einem einzigen WriteLine in einem using Block schreib er genau diese eine Zeile in die Datei und das laut ProcMon ohne Sharing Violation.
Bei einem StringBuilder via Append mit Environment.NewLine oder AppendLine und anschließendem


file.Write(dstr.ToString());
                            file.Flush();

bekomme ich auch ohne Flush eine Sharing Violation. Das selbe passiert bei einigen file.Writeline(); in einer Schleife. Wie gesagt in der Forms Applikation funktioniert es einwandfrei. Am Rechner denke ich auch nicht dass es liegt, da ich es bei mir unter Win7 und am Server getestet habe.

atheos

16.806 Beiträge seit 2008
vor 10 Jahren

Das SharingViolation lässt darauf schließen, dass Du parallel mehrere StreamWriter hast. Kann das sein?
Und so, wie Du den Stream öffnest, funktioniert das halt nicht. Hier wird IIRC kein Sharing erlaubt beim Öffnen der Datei. Das müsste man dann schon via File.Open Method (String, FileMode, FileAccess, FileShare) machen und den entsprechenden Share-Modus übergeben.

Trotzdem finde ich auch diesen Ansatz schlecht.

A
AtHeOS Themenstarter:in
156 Beiträge seit 2005
vor 10 Jahren

Grüß dich,

das hatte ich auch schon probiert. Habe das jetzt testweise nochmals probiert. Selbes Ergebnis.
Gleichzeitiger Zugriff ist in dem Fall nicht möglich, da nur ein Thread in die Datei auf folgende Weise schreibt. btw.: wie egsagtm ind er Forms Applikation funktioniert es.


                    FileStream fs = File.Open(this._LogPath + filename, FileMode.OpenOrCreate, FileAccess.Write);
                    //file = new StreamWriter(this._LogPath + filename, true);
                    file = new StreamWriter(fs);
                    StringBuilder dstr = new StringBuilder();
                    for (int i = 0; i < count; i++)
                    {
                        DebugItem di = this.myQueue.Peek();


                        FormatMessage = String.Format("{0,-15}", di.level.ToString()) + di.date.ToString("yyyy-MM-dd HH:mm:ss") + "." + di.date.Millisecond + "\t\t" + di.user + "\t\t" + di.message;
                        this.myQueue.Dequeue();
                        Debug.WriteLine(FormatMessage);
                        if (this._Level <= di.level)
                        {
                            try
                            {
                                dstr.AppendLine(FormatMessage);

                            }
                            catch { }
                            NewDebugMessage(FormatMessage);
                        }
                    }
                    //SchreibOperation
                    try
                    {
                        if (dstr.Length > 0)
                        {
                            file.Write(dstr.ToString());
                            file.Flush();
                        }
                    }
                    catch { }
                    
                    file.Close();
                    fs.Close();

16.806 Beiträge seit 2008
vor 10 Jahren

Das wird ja immer schlimmer 😉
Was ist das denn für eine Queue? evtl. (aufgrund des Peeks) eine thread-unsichere Collections.Queue?
Warum öffnest Du mit OpenOrCreate statt mit Append?
Was ist das Ziel des ganzen?

Willst Du hier dauerhaft ein Stream offen halten und solange in eine Datei schreiben, bis die Queue geschlossen wird?
Oder willst Du so lange in die Queue schreiben, bis die Queue leer ist?
Läuft das ganze in einem eigenen Thread?

Im Endeffekt erfindest Du das Rad komplett neu; keine Lust mal NLog und den dort mitlerweile standardisierten Logger anzuschauen?
Auf alle Fälle ist Dein Konstrukt sehr unsauber - und je mehr Details zu preis gibst desto schlimmer wirds 😉

A
AtHeOS Themenstarter:in
156 Beiträge seit 2005
vor 10 Jahren

Hallo,

Das wird ja immer schlimmer 😉

Danke für die Blumen, sehr Kontext bezogen.

Was ist das denn für eine Queue? evtl. (aufgrund des Peeks) eine thread-unsichere Collections.Queue?

Nein. Wie gesagt in der Forms Applikation funktioniert es.

Warum öffnest Du mit OpenOrCreate statt mit Append?

Weil nicht nur in eine Datei geschrieben wird und es sein kann, dass es die Datei nicht gibt. Wobei das finde ich jetzt nicht so verwerflich, dafür gibt es diese Optionen ja.

Willst Du hier dauerhaft ein Stream offen halten und solange in eine Datei schreiben, bis die Queue geschlossen wird?

Nein. Im Intervall x werden die einzelnen Elemente der Queue in die Datei geschrieben.

Läuft das ganze in einem eigenen Thread?

Ja

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo AtHeOS,

es sollte eigentlich gehen. Da sind wir uns ja einig. Also ein Fall für [Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden.

herbivore

A
AtHeOS Themenstarter:in
156 Beiträge seit 2005
vor 10 Jahren

Danke für die Hilfe.

Das Problem war ein Event, welches ich für die Forms App auslöse.

lg