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#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
随机推荐
- 【Quartz】定时器初步实验(一)
原文:[Quartz]定时器初步实验(一) 以前就了解了Quartz这个定时框架,但是一直没有认真的去关注他,最近忽然看到已经更新到3.0.4支持异步操作了所以就写个简单的小例子看看好用不. ...
- debian安装node.js
1,先下载nodejs: # wget http://nodejs.org/dist/v0.8.7/node-v0.8.7.tar.gz 2,解压文件 # tar xvf node-v0.8.7.ta ...
- [nginx]invalid number of arguments
invalid number of arguments nginx出现以下的错误,基本上错误的原因就是少了后面的分号导致. invalid number of arguments
- Layui 2.0.0 正式发布:潜心之作,开箱即用的前端UI框架(确实很多内容)
Hi,久违了.处暑逼近之际,潜水半年的 layui 是时候出来透透气了.我们带来的是全新的 2.0 版本,一次被我们定义为“破茧重生”的倾情之作.如果你已曾用过 layui,你将真正感受到一次因小而大 ...
- WPF 打印不显示的元素
<Window x:Class="_097打印不显示的元素.MainWindow" xmlns="http://schemas.microsoft.c ...
- ARM中 __IO的作用解析
__IO在头文件中预定义 #define __IO volatile volatile 影响编译器编译的结果, 指出:volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要 ...
- MyCat的初步了解
MyCat 1 开源数据库中间件 MyCat 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据 ...
- AndroidStudio问题汇总
1.Error:Execution failed for task ':app:preDebugAndroidTestBuild'.> Conflict with dependency 'com ...
- Excel导入导出各种方式分析
1.引言 1.1解决哪些问题 现在很多公司用的导出基本上采用的通过gridView导出excel,此种导出存在以下几种问题 1.数据量大的时候有时导出有时会让浏览器卡死,因为导出的excel不是真 ...
- Elasticsearch 6.1.2 搭建及使用教程一
安装包: es6.1.2 es-head 开发环境:jdk 1.8 搭建流程一一说明: 将下载好的es解压后找到如下图文件 打开后如下图所示配置(已添加详细注释): # 集群的名字 cluster.n ...