Ich habe ein seltsames Problem in der Produktion mit einem Windows-Dienst zufällig angetroffen und würde jede Hilfe bei der Ursachenanalyse schätzen.
Der Dienst ist in C # geschrieben und wird auf einem Rechner mit .NET 4.5 bereitgestellt (obwohl ich ihn auch mit .NET 4.5.1 reproduzieren kann).
Der gemeldete Fehler lautet:
%Vor%Ich habe die Quelle der Ausnahme auf Aufrufe von Console.WriteLine () und Console.Error.WriteLine () in einem Logger eingegrenzt. Diese werden von mehreren Threads aufgerufen und bei hoher Auslastung tritt der Fehler auf und der Dienst hängt.
Laut MSDN muss jedoch die gesamte Konsole verwendet werden Die Klasse ist Thread-sicher (und ich habe es vorher aus mehreren Threads verwendet, keine Probleme). Außerdem wird dieses Problem nicht angezeigt, wenn derselbe Code wie eine Konsolenanwendung ausgeführt wird. nur von einem Windows-Dienst. Und schließlich zeigt der Stack-Trace für die Exception einen internen Aufruf von SyncTextWriter in der Konsolenklasse, die die in der Exception genannte synchronisierte Version sein sollte.
Weiß jemand, ob ich hier etwas falsch mache oder einen Punkt verpasse? Eine mögliche Problemumgehung scheint die Out- und Err-Streams nach / dev / null umzuleiten, aber ich würde eine detailliertere Analyse bevorzugen, die meines Wissens nach .NET nicht funktioniert.
Ich habe einen Repro-Windows-Dienst erstellt, der den Fehler ausgibt, wenn er versucht wird. Code ist unten.
Serviceklasse:
%Vor%Hauptklasse:
%Vor%Installer-Klasse:
%Vor%Wenn Sie diesen Dienst mit InstallUtil.exe installieren und starten, werden die Fehler im Ereignisprotokoll protokolliert.
Console.Out und Console.Error sind beide Thread-sicher, da sie jeweils einen threadsicheren Wrapper (über TextWriter.Synchronized) für die Konsolenausgabe und den Fehlerstream TextWriters zurückgeben. Diese Thread-Sicherheit gilt jedoch nur, wenn Console.Out und Console.Error TextWriter für verschiedene Streams sind.
Der Grund dafür, dass Ihr Code bei der Ausführung als Windows-Dienst eine Ausnahme auslöst, ist, dass in diesem Fall die Ausgabe- und Fehler-TextWriter auf StreamWriter.Null gesetzt sind, was ein Singleton ist. Ihr Code ruft sowohl Console.WriteLine als auch Console.Error.WriteLine auf und verursacht die Ausnahme, wenn ein Thread Console.WriteLine zur gleichen Zeit aufruft, zu der ein anderer Thread Console.Error.WriteLine aufruft. Dies bewirkt, dass derselbe Stream gleichzeitig von zwei Threads geschrieben wird, was dazu führt, dass beim Kopieren des Speichers die "Wahrscheinliche I / O-Race-Bedingung erkannt wird". Ausnahme. Wenn Sie nur Console.WriteLine oder nur Console.Error.WriteLine verwenden, werden Sie feststellen, dass die Ausnahme nicht mehr auftritt.
Hier ist ein minimales Nicht-Service-Konsolenprogramm, das das Problem demonstriert:
%Vor%Tags und Links .net c# windows-services console