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, ...
随机推荐
- ios 打tag
修改spec文件的version: git commit -am"version 0.1.1" git push origin master -u git tag 0.1.1 gi ...
- JTemplate学习(四)
注释.自定方法.模板嵌套子模板.循环输出不同class <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "htt ...
- geoserver 开发1
打开项目,会看见下面这些包(其实还有很多插件之类的包,我都删除了) 5)可以从Eclipse启动GeoServer了. 如果你已经安装了GeoServer,现在也可以打开它的登陆页面进行操作. 三 结 ...
- 白盒静态自动化测试工具:PMD使用指南
参考文献:http://www.oschina.net/p/pmd/http://www.cnblogs.com/flyme/archive/2011/09/09/2172548.htmlhttp:/ ...
- 社交类APP原型模板分享——Tinder
Tinder是国外的一款手机交友APP,作用是基于用户的地理位置,每天“推荐”一定距离内的四个对象,根据用户在 Facebook 上面的共同好友数量.共同兴趣和关系网给出评分,得分最高的推荐对象优先展 ...
- 社交类APP原型模板分享——微信
微信是一款社交类的APP应用——聊天软件,支持多人群聊. 交互效果主要有滚动内容界面.选择组件触发按钮状态变化.点击下拉展开列表.点击弹出面板等交互操作. 本原型由国产原型工具-Mockplus制作完 ...
- 1、HttpClient初探
HttpClient是它的核心接口.可以理解为一个简单的浏览器. 主要方法有: getParams(); 获取运行参数 getConnectionManager(); 获取连接管理器.连接管理器中 ...
- python协程函数、递归、匿名函数与内置函数使用、模块与包
目录: 协程函数(yield生成器用法二) 面向过程编程 递归 匿名函数与内置函数的使用 模块 包 常用标准模块之re(正则表达式) 一.协程函数(yield生成器用法二) 1.生成器的语句形式 a. ...
- 2018.10.19 NOIP训练 yk赚钱记(01分数规划)
传送门 其实是一个裸的最优比率生成树. 注意精度的控制就行了. 代码
- hdu-1058(动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1058 题意:求只由2,3,5,7的乘积组成的数,输出格式见output 思路:开始想打表,后来打表超时 ...