加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 如何使ASP.Net MVC控制器动作异步

发布时间:2020-12-16 07:13:18 所属栏目:asp.Net 来源:网络整理
导读:我的愿望是创建一个MVC控制器Action,它可以异步执行长时间运行的i / o操作.我的目标是避免在这个长时间运行的方法完成时绑定ASP.Net线程池中的线程. 该行动打了两个电话. 第一个调用是第三方dll,它不包含任何异步方法.这个DLL从专有数据库读取并执行相当复杂
我的愿望是创建一个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);
}

我想打电话给3rdPartyComponent等待.我最初的想法是这样做:

var parameters = await Task.Run(() => 3rdPartyComponent.TakesLongTime()).ConfigurateAwait(false);

但我已经阅读了几位主题专家明确表示在asp.net MVC Action中使用Task.Run()会适得其反,永远不应该这样做.

3rdPartyComponent是一个黑盒子的编译代码,它不能改变添加异步方法.

是否有任何方法可以调用3rdPartyComponent,以便整个Action运行而不会占用asp.net线程池中的线程?

解决方法

The first call is to a 3rd party dll that does not contain any asynchronous methods. This dll reads from a proprietary database and does fairly complex cpu-bound processing.

I would like to make the call to 3rdPartyComponent awaitable.

Is there any way to make the call to 3rdPartyComponent awaitable,so that the entire Action runs without tying up a thread in the asp.net thread pool?

代码已经尽可能好了. Task.Run和Task.Factory.StartNew都不会给你带来任何好处(即使你传递了LongRunning标志).

由于第三方dll执行CPU绑定代码,因此需要一个线程.即使您可以修改它,也只能使db访问(I / O工作)异步;根据定义,CPU工作是同步的,从你的描述来看,听起来像CPU工作的工作在大多数时候都是如此.

关于在ASP.NET上避免Task.Run(以及甚至更糟的Task.Factory.StartNew)的全部观点是它们导致效率较低的行为.通过释放ASP.NET请求线程,您只需将线程返回到线程池,而不使用它;关于ASP.NET请求线程没什么神奇或特殊的.因此,Task.Run通过切换到另一个线程池线程来释放一个线程池线程,而使用LongRunning的Task.Factory.StartNew通过创建一个全新的线程释放一个线程池线程,将工作安排到该线程,然后拆除该线程最后的线程(此行为未记录,也未指定,但它是当前观察到的行为).

所以你最终做的只是招致不必要的线程切换(在StartNew的情况下,是一个完整的额外线程). ASP.NET旨在处理同步和异步工作;如果你有同步代码,最好的办法就是直接执行它,就像你的代码已经在做的那样.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读