2016-06-16 1 views
3

У меня такая же проблема, как и у this person had. Однако на вопрос был дан ответ, используя .Net 4.5, но у меня только .Net 4.0.Вызов метода для потока пользовательского интерфейса изнутри Lock() с .Net 4.0

Так что я создал свой собственный асинхронный семафор на основе this tutorial и реализован мой код на основе дополнительных комментариев парня, который разместил Anwer:

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(); 
    } 
} 

Это не работает для меня, хотя, бар называется параллельно ,

+0

Вы выпускаете семафор до того, как произойдет асинхронный процесс. Вместо этого вы должны использовать 'await'. – SLaks

+0

@SLaks: У меня нет .Net 4.5. – gartenriese

+1

Затем используйте Microsoft.Bcl.Async. – SLaks

ответ

4

Вы слишком рано выпускаете семафор. Отпустите его в обработчике ContinueWith в конце.

Знаете ли вы, что Foo() будет немедленно возвращаться, независимо от того, что на самом деле выполняется синхронизированный код?

if (Dispatcher.FromThread(Thread.CurrentThread) != null) также очень подозрительно. Вы должны знать, нужно ли вам маршалировать или нет.

Поскольку продолжения могут быть встроены, трудно предсказать, на каком потоке он фактически работает. Это довольно неприятный детерминизм в TPL. Вероятно, вы должны указать планировщик задач пользовательского интерфейса для этого продолжения. Таким образом, вам никогда не нужно маршалировать.

Также обратите внимание, что вы можете использовать await на .NET 4.0, поэтому, возможно, этот вопрос спорный.

Смежные вопросы