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#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
随机推荐
- 用 theano 求解 Logistic Regression (SGD 优化算法)
1. model 这里待求解的是一个 binary logistic regression,它是一个分类模型,参数是权值矩阵 W 和偏置向量 b.该模型所要估计的是概率 P(Y=1|x),简记为 p, ...
- struts1和struts2安全线
Servlet的生命周期是"初始化->init->service->destroy->卸载". 这里大家都知道,我们在web.xml里面定义一个servle ...
- WPF 遍历DataTemplate(获取所有控件)
原文:WPF 遍历DataTemplate(获取所有控件) 情况1:在设定DataTemplate的Name,并且他是在前台表示时,获取DataTemplate里的指定控件. 方法: http://b ...
- js 操作样式
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂 先上效果图 正常样式 拖动时样式 好下面 开始吧 ==================================== ...
- WPF的点击穿透
1.background 为{x:null} 或 鼠标点击会穿透,如果不想让一个透明的border点击穿透,设置透明色Transparent时就可以点到这个看起来透明的border 2.当依赖属性I ...
- Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效
原文:Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效 /// <summary> /// Image merge process. /// </summar ...
- Android adb你真的会用吗?
前言 本文基于Android官方文档, 以及个人工作的使用经验, 总结下adb的常用用法, 备忘. 1.adb 简介 adb全名Andorid Debug Bridge. 顾名思义, 这是一个Debu ...
- grep专题
grep -R --include="*.cpp" key dir[指定文件的扩展名] 上述命令的含义: 在dir目录下递归查找所有.cpp文件中的关键字key grep -r m ...
- SendMessage发送自定义消息及消息响应(VC版)
控件向父窗体发送自定义消息,父窗体定义处理此消息的函数 程序源代码(整个工程)下载:http://download.csdn.net/detail/qq2399431200/6274793 效果描述 ...