2016-06-16 9 views
3

Ich habe das gleiche Problem wie this person had. Die Frage wurde jedoch mit .Net 4.5 beantwortet, aber ich habe nur .Net 4.0.Aufrufen von Methode auf UI-Thread von innerhalb einer Sperre() mit. NET 4.0

Also habe ich meine eigene asynchrone Semaphore basierend auf this tutorial und implementiert meinen Code basierend auf zusätzliche Kommentare der Typ, der anwer posted:

private void Foo() 
{ 
    try 
    { 
     Semaphore.WaitAsync().ContinueWith(previousTask => 
     { 
      if (Dispatcher.FromThread(Thread.CurrentThread) != null) 
      { 
       Bar(); 
      } 
      else 
      { 
       Application.Current.Dispatcher.Invoke(new Action(() => Bar())); 
      } 
     }); 
    } 
    finally 
    { 
     Semaphore.Release(); 
    } 
} 

Dies obwohl für mich nicht funktioniert, Bar parallel aufgerufen .

+0

Sie geben das Semaphor frei, bevor das Async passiert. Sie sollten stattdessen 'erwarten' verwenden. – SLaks

+0

@SLaks: Ich habe .Net 4.5 nicht. – gartenriese

+1

Verwenden Sie dann Microsoft.Bcl.Async. – SLaks

Antwort

4

Sie geben den Semaphor zu früh frei. Lassen Sie es im Handler ContinueWith am Ende los.

Sind Sie sich bewusst, dass Foo() sofort zurückkehrt, unabhängig davon, ob der synchronisierte Code tatsächlich ausgeführt wird?

Die if (Dispatcher.FromThread(Thread.CurrentThread) != null) ist auch sehr verdächtig. Sie sollten wissen ob Sie Marshal oder nicht müssen.

Da Fortsetzungen inline sein können, ist es schwierig vorherzusagen, auf welchem ​​Thread es tatsächlich läuft. Das ist ein ziemlich hässlicher Nicht-Determinismus in der TPL. Sie sollten wahrscheinlich den UI-Taskplaner für diese Fortsetzung angeben. Auf diese Weise müssen Sie nie marshalen.

Beachten Sie auch, dass Sie auf .NET 4.0 erwarten können, also vielleicht diese Frage ist strittig.