与之前《C# 死锁 TaskCompletionSource》类似,还有很多死锁的案例
使用Task异步转同步时,使用不当造成的死锁
1 private void Task_OnClick(object sender, RoutedEventArgs e) 2 { 3 AwaitUsingTask(TestAsync()); 4 Debug.WriteLine("Task_OnClick end"); 5 } 6 private void AwaitUsingTask(Task task) 7 { 8 task.Wait(); 9 //task.Result; 10 }
使用AutoResetEvent异步转同步时,使用不当造成的死锁
1 private void AwaitAutoResetEvent_OnClick(object sender, RoutedEventArgs e) 2 { 3 AwaitUsingAutoResetEvent(TestAsync()); 4 Debug.WriteLine("AwaitAutoResetEvent_OnClick end"); 5 } 6 7 public void AwaitUsingAutoResetEvent(Task task) 8 { 9 AutoResetEvent autoResetEvent = new AutoResetEvent(false); 10 11 task.ContinueWith(t => 12 { 13 autoResetEvent.Set(); 14 }); 15 autoResetEvent.WaitOne(); 16 }
TestAsync:
1 private static async Task TestAsync() 2 { 3 Debug.WriteLine("异步任务start……"); 4 await Task.Delay(2000); 5 Debug.WriteLine("异步任务end……"); 6 }
以上死锁的原因:
- 主执行线程调用子线程后挂起等待子线程结果
- 子线程又需要切换到主线程或者等待主线程返回
- 从而导致两个线程均处在阻塞状态(死锁)
如何避免:
如果已经使用了Async/Await,那尽量不要再使用Task.Wait()/Task.Result,让上下游的方法全部改为Async/Await原则
参考资料: