最近项目数据量较大,使用 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 死锁的更多相关文章

  1. async/task/await

    async/task/await三组合是.NET Framework 4.5带给.NET开发者的大礼,合理地使用它,可以提高应用程序的吞吐能力. 但是它的使用有点绕人,如果不正确使用,会带来意想不到的 ...

  2. 小心C# 5.0 中的await and async模式造成的死锁

    平时在使用C# 5.0中的await and async关键字的时候总是没注意,直到今天在调试一个ASP.NET项目时,发现在调用一个声明为async的方法后,程序老是莫名其妙的被卡住,就算声明为as ...

  3. async、await在ASP.NET[ MVC]中之线程死锁的故事

    场景重构 public ActionResult Index(string ucode) { string userInfo = GetUserInfo(ucode).Result; ViewData ...

  4. [转]小心C# 5.0 中的await and async模式造成的死锁

    原文链接 https://www.cnblogs.com/OpenCoder/p/4434574.html 内容 UI Example Consider the example below. A bu ...

  5. wait 和async,await一起使用引发的死锁问题

    在某个项目开发过程中,偶然间发现在UI线程中async,await,wait三者一起使用会引发一个必然性的死锁问题. 一个简单的实例,代码很简单,在界面上放置一个Button,并在Button的cli ...

  6. 异步方法的意义何在,Async和await以及Task的爱恨情仇,还有多线程那一家子。

    前两天刚感受了下泛型接口的in和out,昨天就开始感受神奇的异步方法Async/await,当然顺路也看了眼多线程那几个.其实多线程异步相关的类单个用法和理解都不算困难,但是异步方法Async/awa ...

  7. Await Async Task

    class Program { static void Main(string[] args) { Console.WriteLine("=======Start Main!======== ...

  8. The Task: Events, Asynchronous Calls, Async and Await

    The Task: Events, Asynchronous Calls, Async and Await Almost any software application today will lik ...

  9. C# Task中的Func, Action, Async与Await的使用

    在说Asnc和Await之前,先说明一下Func和Action委托, Task任务的基础的用法 1. Func Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate, ...

随机推荐

  1. PAT L3-008 喊山(广搜)

    喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤.呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的.原来它是彝族先民用 ...

  2. POSIX systemV共享内存的区别

    POISX共享内存分为两种方式: 1.内存映射文件 特点:共享内存的改变能在文件中体现: 2.共享内存区对象 特点:共享内存的改变在文件上看不出来(实际上根本打不开该文件): 以上两者都是基于mmap ...

  3. [转]docker 基本原理及快速入门

    版权声明:原创作品, 来自海牛部落-青牛,http://hainiubl.com/topics/13 什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud ...

  4. javascript札记

    bind和unbind对应,live和die对应,千万别用bind绑定,用die解除.还有bind可以多次绑定同一个函数,可能会被执行多次同一个函数 正则表达式的使用 var email_reg = ...

  5. exit--进程退出;wait--进程等待;execl--执行程序

    函数原型:void exit(int status) 参数说明:退出状态. 函数原型:pid_t wait(int *status) 头文件:#include<sys/types.h>,# ...

  6. chrome,opera..通过file协议浏览html代码时,发送的ajax请求本地文件,会报跨域错误

    XMLHttpRequest cannot loadfile:///E:/webs/extJS/ext-3.3.0/examples/csdn/combobox.txt?_dc=14147389739 ...

  7. centos7 jenkins安装和使用

    jenkins 安装和使用 1.先安装jdK1.8 和 maven 此步骤省略 2.进入jenkisn 官网 下载https://jenkins.io/download/ Long-term Supp ...

  8. Kubernetes web界面kubernetes-dashboard安装

    本文讲述的是如何部署K8s的web UI,前提是已经有一个k8s集群后,按照如下步骤进行即可.(如下步骤都是在master节点上进行操作) 1.下载kubernetes-dashboard.yaml文 ...

  9. 利用ajaxSubmit()方法实现Form提交表单后回调

    1.      背景 最近在工作中,需要实现网页端图片上传到FTP服务器的功能.上传文件是用Form表单提交数据的方法向后台传输文件流,在此遇到了一个问题:后台在处理完图片上传功能后,需要向前台回传是 ...

  10. 2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)

    [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8951 Solved: 2860 Description 火星 ...