Winforms deadlock (FW 3.5)

03/04/2011 - 14:25 von Armin Zingler | Report spam
Hallo mal wieder,

ich hatte einen TraceListener geschrieben, der eine Form in einem eigenen
Thread (hier: "Trace-Thread") anzeigt. Gegen diesen weiteren UI-Thread spricht
im Prinzip nichts. Der Trace-Thread wird bei der erstmaligen Verwendung des
Listeners gestartet. Darin wird die Form erzeugt und angezeigt. Da der
Tracelistener die Form benötigt, wartet er per ManualResetEvent kurz auf ein
Signal vom Trace-Thread, dass die Form erzeugt wurde:

Listener:
FormCreatedEvent.WaitOne

Im Trace-Thread:
f_Form = New Traceform
FormCreatedEvent.Set

Das funktioniert prinzpiell bestens.


Leider machen mir aber im aktuellen Projekt, das den Listener nutzt, schon wieder
die (Framework-)Internas einen Strich durch die Rechnung:

Ich habe eine Start-Form. In dieser werden innerhalb WndProc per Debug.Writeline die
Messages protokolliert. Die sollten auch in der Traceform erscheinen. Das Problem: Das
Programm hàngt überraschenderweise. Unterbricht man, steht der Haupt-Thread bei:
(nur relevante Frames)

CreateHandle -> WndProc -> Debug.Writeline -> TraceListener -> FormCreatedEvent.WaitOne

Ich wundere mich, dass WaitOne nicht verlassen wird. Der Trace-Thread müsste eigentlich
signalisieren, denn in "New TraceForm" habe ich nichts potentiell blockierendes eingebaut.
Worauf wartet er also? Der Callstack verràt es:

[Deaktiviert oder wartend]
System.Windows.Forms.NativeWindow.CreateHandle
System.Windows.Forms.Control.CreateHandle
System.Windows.Forms.Application.MarshalingControl.MarshalingControl
System.Windows.Forms.Application.ThreadContext.MarshalingControl.get
System.Windows.Forms.WindowsFormsSynchronizationContext.WindowsFormsSynchronizationContext
System.Windows.Forms.WindowsFormsSynchronizationContext.InstallIfNeeded
System.Windows.Forms.Control.Control
System.Windows.Forms.ScrollableControl.ScrollableControl
System.Windows.Forms.ContainerControl.ContainerControl
System.Windows.Forms.Form.Form
AZ.TraceForm.New

Innerhalb CreateHandle steht Monitor.Enter, vermutlich um die Framework-
Internas bei gleichzeitiger Handle-Erzeugung in verschiedenen Threads in
Schuss zu halten. Dagegen spricht ja auch nichts. Die entscheidende Frage
ist aber: Warum wird das Handle der Form schon in ihrem constructor erstellt?
Das passiert doch nur, wenn man es provoziert; was ich ich aber nicht mache.
Genauer betrachtet ist es gar nicht das Handle der Form sondern des
"MarshalingControls", das durchs Framework für interne Marshaling-Zwecke
erzeugt wird. Die Folge ist ein Deadlock weil der Haupthread ja auch gerade
ein Handle für die Start-Form erzeugt.

Was kann ich jetzt für dieses hohle MarshalingControl? Woher kann ich wissen,
dass solche Internas zu solchen Sperren führen? Bei einem "New TraceForm" kann
ich doch wirklich nicht davon ausgehen, dass darin irgendetwas blockiert.
Schließlich sorge ich selbst nicht für eine solche Blockade. Ehrlich gesagt finde
ich meinen Ansatz im Prinzip völlig korrekt! Mir fehlt dadurch etwas die Phantasie,
wie man hier Abhilfe schaffen könnte. Über Ideen dazu würde ich mich echt freuen!


Armin
 

Lesen sie die antworten

#1 Armin Zingler
07/04/2011 - 15:46 | Warnen spam
Am 03.04.2011 14:25, schrieb Armin Zingler:
[Deaktiviert oder wartend]
System.Windows.Forms.NativeWindow.CreateHandle
System.Windows.Forms.Control.CreateHandle
System.Windows.Forms.Application.MarshalingControl.MarshalingControl



Wie kann ich die Erzeugung eines MarshalingControls verhindern oder
kontrollieren?

Armin

Ähnliche fragen