Tom*_*gan 5 asp.net-mvc async-await
我的愿望是创建一个MVC控制器Action,它可以异步执行长时间运行的i/o操作.我的目标是避免在这个长时间运行的方法完成时绑定ASP.Net线程池中的线程.
该行动打了两个电话.
第一个调用是第三方dll,它不包含任何异步方法.这个DLL从专有数据库读取并执行相当复杂的cpu绑定处理.返回可能需要几秒钟的时间.
第二个调用使用第一个调用的结果作为使用Entity Framework传递给数据库查询的参数.
简化,这是动作:
public async Task<ActionResult> MyActionAsync(arg1, arg2)
{
var parameters = 3rdPartyComponent.TakesLongTime(arg1, arg2);
Task<List<MyClass>> genericList = null;
using (DbContexts.MyDbContext db = new DbContexts.MyDbContext())
{
genericList = await db.Database.SqlQuery<MyClass>(sql,parameters).ToListAsync();
}
return View("MyView", genericList);
}
Run Code Online (Sandbox Code Playgroud)
我想打电话给3rdPartyComponent等待.我最初的想法是这样做:
var parameters = await Task.Run(() => 3rdPartyComponent.TakesLongTime()).ConfigurateAwait(false);
Run Code Online (Sandbox Code Playgroud)
但我已经阅读了几位主题专家明确表示在asp.net MVC Action中使用Task.Run()会适得其反,永远不应该这样做.
3rdPartyComponent是一个黑盒子的编译代码,它不能改变添加异步方法.
是否有任何方法可以调用3rdPartyComponent,以便整个Action运行而不会占用asp.net线程池中的线程?
第一个调用是第三方dll,它不包含任何异步方法.这个DLL从专有数据库读取并执行相当复杂的cpu绑定处理.
我想打电话给3rdPartyComponent等待.
是否有任何方法可以调用3rdPartyComponent,以便整个Action运行而不会占用asp.net线程池中的线程?
代码已经尽可能好了.既Task.Run不会也不Task.Factory.StartNew会给你任何好处(即使你通过了LongRunning旗帜).
由于第三方dll执行CPU绑定代码,因此需要一个线程.即使您可以修改它,也只能使db访问(I/O工作)异步; 根据定义,CPU工作是同步的,从你的描述来看,听起来像CPU工作的工作在大多数时候都是如此.
关于避免Task.Run(甚至更糟Task.Factory.StartNew)ASP.NET 的全部观点是它们导致行为效率降低.通过释放ASP.NET请求线程,您只需将线程返回到线程池,而不使用它; 关于ASP.NET请求线程没什么神奇或特殊的.因此Task.Run,通过切换到另一个线程池线程Task.Factory.StartNew来LongRunning释放一个线程池线程,并通过创建一个全新的线程释放一个线程池线程,将工作安排到该线程,然后在最后拆除该线程(此行为不是记录或指定,但它是当前观察到的行为).
所以你最终做的只是招致不必要的线程切换(在StartNew整个额外线程的情况下).ASP.NET旨在处理同步和异步工作; 如果你有同步代码,最好的办法就是直接执行它,就像你的代码已经在做的那样.
| 归档时间: |
|
| 查看次数: |
1488 次 |
| 最近记录: |