Ich bin auf diese Situation gestoßen, wo die folgende plinq-Anweisung im statischen Konstruktor blockiert wird:
%Vor%Es passiert nur, wenn ein Konstruktor statisch ist. Kann mir das bitte jemand erklären?
Ist es ein TPL-Fehler? Compiler? Ich?
Es ist generell gefährlich, Threading-Code von einem statischen Konstruktor aufzurufen. Um sicherzustellen, dass der statische Konstruktor nur einmal ausgeführt wird, führt die CLR den statischen Konstruktor unter einer Sperre aus. Wenn der Thread, der den statischen Konstruktor ausführt, auf einen Hilfsthread wartet, besteht das Risiko, dass der Hilfsthread aus irgendeinem Grund auch die CLR-interne Sperre benötigt, und das Programm blockiert den Prozess.
Hier ist ein einfacheres Codebeispiel, das das Problem veranschaulicht:
%Vor%Abschnitt 10.5.3.3 "Rassen und Deadlocks" der ECMA CLI-Spezifikation garantiert Folgendes:
Bei der Typinitialisierung wird kein Deadlock erstellt, es sei denn, es handelt sich um einen Code von einem Typinitialisierer (direkt oder indirekt) explizit aufgerufen ruft blockierende Operationen auf.
So wird ein Typinitialisierer (d. h. ein statischer Konstruktor) nicht blockiert, vorausgesetzt, dass keine Operation im statischen Konstruktor den Thread blockiert. Wenn der statische Konstruktor blockiert, riskiert er einen Deadlock.
Obwohl der Grund bereits erläutert wurde, warum Sie in einem statischen Konstruktor keine Threading-Arbeit ausführen möchten, dachte ich, ich würde hinzufügen, dass der "richtige" Weg dies stattdessen mit einem statischen Lazy<T>
. Dies ist auch effizienter, da die Arbeit zum Erzeugen dieser Ressourcen so lange dauert, bis diese Ressourcen tatsächlich benötigt werden.
Für was es wert ist, tritt das Problem nicht auf Mono auf:
%Vor%Haben Sie eine Windows-kompilierte Binärdatei, damit ich die generierte MSIL vergleichen kann? Ich bin nicht überzeugt, dass dies ein Problem nur für die Bibliothek ist, und ich bin neugierig:)
Der Vergleich der IL war etwas unordentlich, also entschied ich mich, beide Binaries auf beiden Plattformen zu testen. Hehe Ich habe meine alte Windows Virtual Machine wiederbelebt, nur um das zu testen:)
Das Ausführen der VS-kompilierten Binärdateien auf Mono ist kein Problem. Sie könnten es unter Windows mit 2.10.1 (http://www.go-mono.com/mono-downloads/download.html), nur 77.4Mb:)
versuchen( Ich habe eine benutzerdefinierte Mono 2.11 auf Linux verwendet, so könnte es sein, dass die Feature-Unterstützung noch nicht abgeschlossen ist )
%Vor%Ich habe auch bemerkt, dass ein CTRL-C bei der Ausführung von Windows aus dem Schloss ausbrechen kann. Wird posten wenn ich mehr dazu finde.
Nun, bei der Installation von Mono werden Kreise ausgeführt, um die Installation von VSExpress auch unter Windows zu installieren. Die Installation von Mono wurde in 4 Minuten beendet und ergab:
%Vor%Kein Deadlock :) Jetzt bleibt nur noch zu warten, dass VSExpress (für immer) installiert wird und es alle Debugging-Tools (unbekannt) gibt, und dann haben Sie eine Chance (wahrscheinlich bis spät in die Nacht). CU später
Tags und Links .net c# task-parallel-library plinq