我最近遇到了类似此处所述的死锁问题:An async/await example that causes a deadlock
此问题与以下问题无关。
因为我可以访问代码的异步部分,所以我可以使用@ stephen-cleary在他的博客文章http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
中描述的解决方案所以我在第一个等待的任务中添加了ConfigureAwait(false)
。
由于受影响的代码量大,我无法使用第二个解决方案(到处都放置async
。
但是我一直在问自己,如果我不能修改被调用的异步代码(例如:extern API)怎么办?
因此,我想出一个避免死锁的解决方案。 Join
任务的一种方式。 Join
是指一种等待目标任务结束而又不阻止当前线程上运行的其他任务的方法。
代码如下:
public static class TaskExtensions
{
public static void Join(this Task task)
{
var currentDispatcher = Dispatcher.CurrentDispatcher;
while (!task.IsCompleted)
{
// Call back the dispatcher to allow other Tasks on current thread to run
currentDispatcher.Invoke(delegate { }, DispatcherPriority.SystemIdle);
}
}
}
我想强调的是,我不确定此方法的正确名称是Join
。
我的问题是为什么Task.Wait()
不能以这种方式实现或可以选择以这种方式使用?
答案 0 :(得分:2)
此"closeOnClickModal". Expected Boolean, got String.
方法只是忙于等待任务完成,并添加了等效的Join
。通过像这样反复调用调度程序,您实际上实现了使UI保持活动状态的嵌套消息泵。
这是一个非常糟糕的主意,因为它会将CPU驱动到100%。
您确实需要正确对待UI消息循环,并在等待时退出UI线程。 Application.DoEvents()
很棒。
您说您真的要避免使所有代码异步感知,因为这将需要大量工作。也许您可以聪明地使用await
模式来避免很多工作。由于此操作在UI线程上运行,因此此类调用的频率应非常低。这意味着由此造成的开销也非常低,这不是问题。