c# async Task await Result 死锁
最近项目数据量较大,使用 async Task异步增加执行效率
遇到问题,当前有2个计算非常耗时,现在需要你优化一下,这2个计算并行执行,2个计算执行完成后将2个结果sum返回给用户
当前我是这样实现的
public async Task<ActionResult> Index()
{
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}begin"); try
{
var t1Rlt = Test1();
var t2Rlt = Test2();
var a = t1Rlt.Result;
var b = t2Rlt.Result;
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}结果【{a + b}】");
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}end");
}
catch (Exception ex)
{ throw;
}
return View();
} public async Task<int> Test1()
{
return await Task.Run(() =>
{
for (int i = ; i < ; i++)
{
Thread.Sleep();
System.Diagnostics.Debug.WriteLine($"子①====线程{Thread.CurrentThread.ManagedThreadId}打印{i}");
}
return ;
});
} public async Task<int> Test2()
{
return await Task.Run(() =>
{ for (int i = ; i < ; i++)
{
Thread.Sleep();
System.Diagnostics.Debug.WriteLine($"子②====线程{Thread.CurrentThread.ManagedThreadId}打印{i}");
}
return ;
});
}
Index执行时大家觉得怎么样 返回300 是吧,我也这样以为了,但是实践是检验结果的唯一方式,程序执行后出错
“计算函数 result.get 超时 需要以不安全的方式中止”
呃。。。之前我确实是用例很多 async task 了 上面代码也没错 先并行执行,然后再去结果计算,但这样是不行的 因为
微软考虑到线程间切换如何保证程序的执行顺序不错乱
大家可以参考下这篇文章 https://www.cnblogs.com/OpenCoder/p/4434574.html 上面内容的大致意思就是说在使用await and async模式时,await关键字这一行后面的代码块会被一个context(也就是上面提到的ASP.NET request contex和UI context)线程继续执行,
如果我们将本例中调用top-level method的线程称为线程A(即context线程),由于GetJsonAsync方法也是由线程A调用的,所以当GetJsonAsync方法中await的GetStringAsync方法执行完毕后,
GetJsonAsync需要重新使用线程A执行await代码行之后的代码,而现在由于线程A在top-level method的代码中因为访问了jsonTask.Result被阻塞了
(因为线程A调用top-level method代码中jsonTask.Result的时候,await的GetStringAsync的Task还没执行完毕,所以被线程A阻塞),
所以GetJsonAsync无法重新使用线程A执行await代码行之后的代码块,也被阻塞,所以形成了死锁。也就是说top-level method代码中线程A因为
等待GetJsonAsync中await的GetStringAsync结束被阻塞,而GetStringAsync也等待线程A在top-level method的阻塞结束获得线程A来执行GetJsonAsync中await代码行后面的代码也被阻塞,
两个阻塞相互等待,相互死锁。 现在抛出正确写法供各位小伙伴参考
public async Task<ActionResult> Index()
{
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}begin"); try
{
var t1Rlt = Test1();
var t2Rlt = Test2();
var a = await t1Rlt;
var b = await t2Rlt;
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}结果【{a + b}】");
System.Diagnostics.Debug.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}end");
}
catch (Exception ex)
{ throw;
}
return View();
} public async Task<int> Test1()
{
return await Task.Run(() =>
{
for (int i = ; i < ; i++)
{
Thread.Sleep();
System.Diagnostics.Debug.WriteLine($"子①====线程{Thread.CurrentThread.ManagedThreadId}打印{i}");
}
return ;
});
} public async Task<int> Test2()
{
return await Task.Run(() =>
{ for (int i = ; i < ; i++)
{
Thread.Sleep();
System.Diagnostics.Debug.WriteLine($"子②====线程{Thread.CurrentThread.ManagedThreadId}打印{i}");
}
return ;
});
}
执行效果
截图执行结果是想告诉大家 await 执行结束后 主线程由那个线程接管 是随机的 不知道的小伙伴记住吧
c# async Task await Result 死锁的更多相关文章
- async/task/await
async/task/await三组合是.NET Framework 4.5带给.NET开发者的大礼,合理地使用它,可以提高应用程序的吞吐能力. 但是它的使用有点绕人,如果不正确使用,会带来意想不到的 ...
- 小心C# 5.0 中的await and async模式造成的死锁
平时在使用C# 5.0中的await and async关键字的时候总是没注意,直到今天在调试一个ASP.NET项目时,发现在调用一个声明为async的方法后,程序老是莫名其妙的被卡住,就算声明为as ...
- async、await在ASP.NET[ MVC]中之线程死锁的故事
场景重构 public ActionResult Index(string ucode) { string userInfo = GetUserInfo(ucode).Result; ViewData ...
- [转]小心C# 5.0 中的await and async模式造成的死锁
原文链接 https://www.cnblogs.com/OpenCoder/p/4434574.html 内容 UI Example Consider the example below. A bu ...
- wait 和async,await一起使用引发的死锁问题
在某个项目开发过程中,偶然间发现在UI线程中async,await,wait三者一起使用会引发一个必然性的死锁问题. 一个简单的实例,代码很简单,在界面上放置一个Button,并在Button的cli ...
- 异步方法的意义何在,Async和await以及Task的爱恨情仇,还有多线程那一家子。
前两天刚感受了下泛型接口的in和out,昨天就开始感受神奇的异步方法Async/await,当然顺路也看了眼多线程那几个.其实多线程异步相关的类单个用法和理解都不算困难,但是异步方法Async/awa ...
- Await Async Task
class Program { static void Main(string[] args) { Console.WriteLine("=======Start Main!======== ...
- The Task: Events, Asynchronous Calls, Async and Await
The Task: Events, Asynchronous Calls, Async and Await Almost any software application today will lik ...
- C# Task中的Func, Action, Async与Await的使用
在说Asnc和Await之前,先说明一下Func和Action委托, Task任务的基础的用法 1. Func Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate, ...
随机推荐
- php 的多进程实践
php的多进程处理依赖于pcntl扩展,通过pcntl_fork创建子进程来进行并行处理. 例1如下: <?php $pid = pcntl_fork(); if($pid == -1) { ...
- win10下zip安装mysql5.7的一些问题
一.MySQL下载地址: http://dev.mysql.com/downloads/mysql/ 我们下载zip版本的 二.解压zip文件 三.复制一份里面的my-default.ini为 ...
- IIS支持IPA、APK文件的下载
IIS里MIME类型中默认是没有ipa,apk文件的,所以无法直接通过网络下载. 解决方法如下: 1.打开IIS信息服务管理器,选中自已的网站,在右边面板中找到MIME类型. 2.双击打开,点击右 ...
- 201621123008 《Java程序设计》 第三周学习总结
1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词,如类.对象.封装等 关键词:类,构造函数,方法重载,方法覆盖,封装,继承,多态,类被加载的过程,static,abstract, ...
- 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)
传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...
- gj10 python socket编程
10.1 HTTP.Socket.TCP这几个概念 五层网络模型 socket 不属于任何协议,是一个API,通过socket 可以和传输层的打交道,然后在之上可以实现自己的功能和协议 10.2 cl ...
- web大文件上传(web应用---SSH框架)
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- dropzonejs中文翻译手册
由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术:HTML5的api,作为一名前端的菜鸟,没什么可说的,直接分享自己学习的资料: 关于HTML5 的这些新的特性大 ...
- MFC框架仿真<二>
- Mouse Touch Stylus
Mouse操作: preview mouse down, StylusDevice:null mouse down,StylusDevice:null preview mouse up, Stylus ...

