與之前《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原則
參考資料:
- Async/Await異步程式設計中的最佳做法