C# 死锁 Task/AutoResetEvent
与之前《C# 死锁 TaskCompletionSource》类似,还有很多死锁的案例
使用Task异步转同步时,使用不当造成的死锁
private void Task_OnClick(object sender, RoutedEventArgs e)
{
AwaitUsingTask(TestAsync());
Debug.WriteLine("Task_OnClick end");
}
private void AwaitUsingTask(Task task)
{
task.Wait();
//task.Result;
}
TestAsync:
1 private static async Task TestAsync()
2 {
3 Debug.WriteLine("异步任务start……");
4 await Task.Delay(2000);
5 Debug.WriteLine("异步任务end……");
6 }
使用AutoResetEvent不当,造成的死锁
private void AwaitAutoResetEvent_OnClick(object sender, RoutedEventArgs e)
{
AwaitUsingAutoResetEvent(TestAsync());
Debug.WriteLine("AwaitAutoResetEvent_OnClick end");
} public void AwaitUsingAutoResetEvent(Task task)
{
AutoResetEvent autoResetEvent = new AutoResetEvent(false); task.ContinueWith(t =>
{
autoResetEvent.Set();
});
autoResetEvent.WaitOne();
}
或者以终止状态=true为参数的AutoResetEvent,也是会死锁的,如下:
private int index = ;
private async void AwaitAutoResetEvent_OnClick(object sender, RoutedEventArgs e)
{
await AwaitUsingAutoResetEvent(index++);
}
AutoResetEvent autoResetEvent = new AutoResetEvent(true);
public async Task AwaitUsingAutoResetEvent(int ind)
{
autoResetEvent.WaitOne();
Debug.WriteLine($"Task.Delay(3000) start{ind}");
await Task.Delay();
Debug.WriteLine($"Task.Delay(3000) end{ind}");
autoResetEvent.Set();
}
上面的案例,2次重入,就会暴露死锁的问题了(因为首次是终止的,第二次才会wait)。
那么如何解决?autoResetEvent.WaitOne();放在异步任务中等待即可
当然此方案会多产生一个task(有性能问题),详见AutoResetEvent的正确用法:C# 同步转异步 AutoResetEvent
以上死锁的原因:
- 主执行线程调用子线程后挂起等待子线程结果
- 子线程又需要切换到主线程或者等待主线程返回
- 从而导致两个线程均处在阻塞状态(死锁)
如何避免:
如果已经使用了Async/Await,那尽量不要再使用Task.Wait()/Task.Result,让上下游的方法全部改为Async/Await原则
参考资料:
C# 死锁 Task/AutoResetEvent的更多相关文章
- C# 死锁 TaskCompletionSource
在异步转同步时,使用不当容易造成死锁(程序卡死) 看如下案例: 有一个异步方法 private static async Task TestAsync() { Debug.WriteLine(&quo ...
- C# 同步转异步 AutoResetEvent
当我们的程序运行时,调用了一段异步的逻辑A,这段异步的逻辑无法转化为同步(如动画.下载进度等) 而,我们又需要等待异步逻辑A处理完成,然后再执行其它逻辑B. AutoResetEvent 同步转异步 ...
- C# 异步转同步
当我们的程序运行时,调用了一段异步的逻辑A,这段异步的逻辑无法转化为同步(如动画.下载进度等) 而,我们又需要等待异步逻辑A处理完成,然后再执行其它逻辑B. 那就迫切需要将异步转同步了! //参数bo ...
- C# 异步转同步 TaskCompletionSource
本文通过TaskCompletionSource,实现异步转同步 首先有一个异步方法,如下异步任务延时2秒后,返回一个结果 private static async Task<string> ...
- C# 同步转异步 TaskCompletionSource
当我们遇到一些异步执行又无法等待时的逻辑,比如动画的执行. 而业务上又需要等待逻辑的完成,再去处理后续的操作.这时需要转成异步方法 如下,同步执行一个动画后,再输出日志: private async ...
- C# 异步转同步 PushFrame
异步转同步-PushFrame 本文通过PushFrame,实现异步转同步 首先有一个异步方法,如下异步任务延时2秒后,返回一个结果 private static async Task<stri ...
- AutoResetEvent控制线程用法
本文主要来自一道面试题,由于之前对AutoResetEvent的用户很模糊(即使已经使用过了).面试题题目很简洁:两个线程交替打印0~100的奇偶数.你可以先动手试试,我主要是尝试在一个方法里面完成这 ...
- C# WebApi+Task+WebSocket实战项目演练(四)
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的第四部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
- C#异步Task编程模型实战手册
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的第一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
随机推荐
- qt4.8.7 源码在win7+vs2010环境的x64编译(qt 64位)
由于qt官网上,没有直接提供x64的安装包,但由于项目需要x64的qt,所以,小编不得不下载qt的源码,经历了一次长达约4个小时的编译过程.今年国庆7天,就遭这事上了,哈哈~~~ 几个下载链接: qt ...
- WebService它Soap头验证进入
1.创建一个新的类.如"AuthHeaderUser",在传承"System.Web.Services.Protocols.SoapHeader"类别 2.新W ...
- Xamarin 设置可接受的版本
一共分三个版本,编译版本.最小版本.目标版本(最适应) 一般编译使用最新的版本,目标版本选择最主流的 参考资料 https://docs.microsoft.com/en-us/xamarin/and ...
- SICP 1.9-1.10
1.9 2^102^162^16 2n2^(n)2的(n-1)层次方(每一层都是2次方) 比如 h(4) = 2^(2^(2^2)) = 2^16
- WPF三维图形
原文:WPF三维图形 wpf 三维图形基础生成三维图形的基本思想是能得到一个物体的三维立体模型(model).由于我们的屏幕只有二维,因而我们定义了一个用于给物体拍照的照相机(Camera).拍到的照 ...
- 【摘抄】C# DateTime.Now详解
//2008年4月24日 System.DateTime.Now.ToString("D"); //2008-4-24 System.DateTime.Now.ToString(& ...
- WPF中的资源(一) - 静态资源和动态资源
原文:WPF中的资源(一) - 静态资源和动态资源 WPF中,每个界面元素都含有一个名为Resources的属性,其存储的是以"键-值"对形式存在的资源,而其子级元素在使用这些资源 ...
- socket编程详解,转自http://www.sme-cn.com:82/archives/669
一 Socket简介 Socket翻译过来是套接字,具体含义可自行百度,简言之就是IP:Port的组合,是网络通信的一个窗口,IP就是地址和门牌号(比如长沙市韶山北路81号),Port就是房间号(比 ...
- 图像滤镜艺术---(Instagram)1977滤镜
原文:图像滤镜艺术---(Instagram)1977滤镜 图像特效---(Instagram)1977滤镜 本文介绍1977这个滤镜的具体实现,这个滤镜最早是Instagram中使用的 ,由于Ins ...
- vs2017 cordova调试ios app
https://docs.microsoft.com/en-us/visualstudio/cross-platform/tools-for-cordova/first-steps/ios-guide ...