使用 .Net 4.0 从 Lock() 中调用 UI 线程上的方法
Invoking Method on UI thread from within a Lock() with .Net 4.0
我和this person had有同样的问题。然而问题是用.Net 4.5 回答的,但是我只有.Net 4.0.
所以我基于 this tutorial 创建了自己的异步信号量,并根据发布答案的人的附加评论实现了我的代码:
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();
}
}
虽然这对我不起作用,Bar 是并行调用的。
您释放信号量的时间过早。最后在 ContinueWith
处理程序中释放它。
您是否知道 Foo()
将立即 return 而不管同步代码是否实际运行?
if (Dispatcher.FromThread(Thread.CurrentThread) != null)
也很可疑。您应该知道是否需要编组。
由于可以内联延续,因此很难预测它实际运行在哪个线程上。这是 TPL 中非常讨厌的非确定性。您可能应该为该延续指定 UI 任务调度程序。这样你就不需要编组了。
另请注意,您可以在 .NET 4.0 上使用 await,所以这个问题可能没有实际意义。
我和this person had有同样的问题。然而问题是用.Net 4.5 回答的,但是我只有.Net 4.0.
所以我基于 this tutorial 创建了自己的异步信号量,并根据发布答案的人的附加评论实现了我的代码:
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();
}
}
虽然这对我不起作用,Bar 是并行调用的。
您释放信号量的时间过早。最后在 ContinueWith
处理程序中释放它。
您是否知道 Foo()
将立即 return 而不管同步代码是否实际运行?
if (Dispatcher.FromThread(Thread.CurrentThread) != null)
也很可疑。您应该知道是否需要编组。
由于可以内联延续,因此很难预测它实际运行在哪个线程上。这是 TPL 中非常讨厌的非确定性。您可能应该为该延续指定 UI 任务调度程序。这样你就不需要编组了。
另请注意,您可以在 .NET 4.0 上使用 await,所以这个问题可能没有实际意义。