Mittwoch, 19. Mai 2010

SynchronizationContext.Current == null

Warum ist SynchronizationContext.Current manchmal null?

SynchronizationContext ist eine Klasse, die dabei helfen soll, unabhängig von GUI-Technologien (WPF/WinForms) einen Synchronisierungsmechanismus vom Background-Workerthread zurück zum GUI-Thread zur Verfügung zu stellen (GUI-Thread = der Thread, in dem die GUI-Komponente XY erzeugt wurde).

Möglich dass das hier hilft (dort, wo die oberste GUI-Komponente, sprich Dialog/Window verfügbar ist, also z.B. in deren Konstruktor):
if( SynchronizationContext.Current == null )
SynchronizationContext.SetSynchronizationContext(
new System.Windows.Threading.DispatcherSynchronizationContext( this.Dispatcher )
); // ersetze "this" durch irgendein lebendes GUI-Objekt mit Dispatcher
Bei mir passiert das, wenn ich in einem Unit-Test (NUnit) eine GUI-Komponente öffne (warum sollte man das tun? nicht fragen...). Offensichtlich erzeugt der Testrunner einen neuen Thread für den Testfall (ich benutze die Testrunnerfunktion von Reshaper, aber ich denke Testdriven.NET oder der nunit-Runner macht das genauso). Damit ich dann (WPF-)-GUI-Komponenten aufrufen kann, muß ich die Testfunktion mit [STAThread] markieren (oder ist das schon falsch?).

Dann passiert genau das, dass ich den SynchronizationContext manuell setzen muß, und zwar auf den Dispatcher des obersten Fenster, das in dem Testfall erzeugt wird.

[Update 20.05.]
Ich hatte auch die Situation, dass der SynchronizationContext ein ThreadSynchronizationContext ist und kein DispatcherSynchronizationContext. Für meinen Anwendungsfall (Background-Threads posten ein Ergebnis an den GUI-Thread; was sollte man sonst mit einem SynchronizationContext machen?). Scheint das nicht zu gehen, also muß es sogar so lauten:
if( !(SynchronizationContext.Current is DispatcherSynchronizationContext) )
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext( this.Dispatcher )
);

Keine Kommentare:

Kommentar veröffentlichen