Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 在WebAPI中使用async和许多异步调用_Asp.net_Asp.net Web Api_Async Await - Fatal编程技术网

Asp.net 在WebAPI中使用async和许多异步调用

Asp.net 在WebAPI中使用async和许多异步调用,asp.net,asp.net-web-api,async-await,Asp.net,Asp.net Web Api,Async Await,很抱歉问了beginers,我在这里和网上读了很多帖子,有一些我不明白的地方 据我所知,在WebAPI中使用异步操作主要是出于可伸缩性的原因,因此任何传入的请求都将转移到工作线程,而不是线程,这样就可以提供更多的请求 我的项目由几个巨大的操作组成,这些操作通过EF6多次读取/插入/更新DB。动作如下所示: public async Task<HttpResponseMessage> Get(int id) { PolicyModel response = a

很抱歉问了beginers,我在这里和网上读了很多帖子,有一些我不明白的地方

据我所知,在WebAPI中使用异步操作主要是出于可伸缩性的原因,因此任何传入的请求都将转移到工作线程,而不是线程,这样就可以提供更多的请求

我的项目由几个巨大的操作组成,这些操作通过EF6多次读取/插入/更新DB。动作如下所示:

    public async Task<HttpResponseMessage> Get(int id)
    {
     PolicyModel response = await policyRepository.GetPolicyAsync(id);
     return Request.CreateResponse<PolicyModel>(HttpStatusCode.OK,response);
    }
    public async Task<PolicyModel> GetPolicyAsync(int id)
    {
      PolicyModel response = new PolicyModel();
      User currentUser = await Repositories.User.GetUserDetailsAsync(id);

      if(currentUser.IsNew)
      {
         IEnumerable<Delivery> deliveries = await Repositories.Delivery.GetAvailableDeliveries();
         if(deliveries == null || deliveries.Count() == 0
         {
           throw new Exception("no deliveries available");
         }
         response.Deliveries = deliveries;
         Ienumerable<Line> lines = await Repositores.Delivery.GetActiveLinesAsync();
         lines.AsParallel().ForAll(line => {
         await Repositories.Delivery.AssignLineAsync(line,currentUser);
    }
    ...
      return response;   
    }
公共异步任务Get(int-id)
{
PolicyModel response=等待policyRepository.GetPolicyAsync(id);
返回Request.CreateResponse(HttpStatusCode.OK,response);
}
GetPolicyAsync(int-id)看起来是这样的:

    public async Task<HttpResponseMessage> Get(int id)
    {
     PolicyModel response = await policyRepository.GetPolicyAsync(id);
     return Request.CreateResponse<PolicyModel>(HttpStatusCode.OK,response);
    }
    public async Task<PolicyModel> GetPolicyAsync(int id)
    {
      PolicyModel response = new PolicyModel();
      User currentUser = await Repositories.User.GetUserDetailsAsync(id);

      if(currentUser.IsNew)
      {
         IEnumerable<Delivery> deliveries = await Repositories.Delivery.GetAvailableDeliveries();
         if(deliveries == null || deliveries.Count() == 0
         {
           throw new Exception("no deliveries available");
         }
         response.Deliveries = deliveries;
         Ienumerable<Line> lines = await Repositores.Delivery.GetActiveLinesAsync();
         lines.AsParallel().ForAll(line => {
         await Repositories.Delivery.AssignLineAsync(line,currentUser);
    }
    ...
      return response;   
    }
公共异步任务GetPolicyAsync(int-id) { PolicyModel响应=新的PolicyModel(); User currentUser=await Repositories.User.GetUserDetailsAsync(id); if(currentUser.IsNew) { IEnumerable deliveries=wait Repositories.Delivery.GetAvailableDeliveries(); if(deliveries==null | | deliveries.Count()==0 { 抛出新异常(“无可用交付”); } 响应。交付=交付; Ienumerable lines=wait Repositores.Delivery.GetActiveLinesAsync(); lines.AsParallel().ForAll(line=>{ wait Repositories.Delivery.AssignLineAsync(line,currentUser); } ... 返回响应; } 我没有写完整的代码,但它进行了相当多的工作,它也被分解成几个方法,但这就是它的精神所在

现在我的问题是:在一种方法中使用这么多的等待程序是一种好的做法吗?我发现调试更困难,维护线程上下文更困难,并且为了工人分配,我不应该只使用
Task.Factory.StartNew()
或者调用一个简单的
Task.Delay()
这样请求很快就会转移到工作人员身上? 我知道这不是一个好的实践(始终是异步的),所以在
GetpolicyAsync(int-id)
方法的末尾/开头可能只有一个异步方法

编辑:

正如我在.net中理解的异步方法的机制一样,对于每个异步方法,编译器都在寻找一个空闲线程并让它处理该方法,线程在寻找一个空闲工作线程并将该方法分配给它,然后向编译器报告它是空闲的。因此,如果我们有10个线程,每个线程有10个工作线程,该程序可以处理100个并发异步方法。 回到web开发,IIS为每个应用程序池分配x个线程,例如10个。这意味着异步WebAPI方法可以处理100个请求,但如果其中有另一个异步方法,则可以处理的请求量为50个,依此类推,对吗? 据我所知,为了使WebAPI方法真正异步,我必须调用一个异步方法。现在,由于使用
Task.Factory.StartNew()
,这是一种不好的做法,我必须至少使用
Task.Delay()

我真正想要的是异步WebAPI方法的可伸缩性和同步方法的上下文感知

在我迄今为止看到的所有示例中,它们只显示了非常简单的代码,但在现实生活中,方法要复杂得多


谢谢

将许多
等待
放在一个方法中没有错。如果该方法对您来说太复杂,您可以将其分为几个方法:

public async Task<PolicyModel> GetPolicyAsync(int id)
{
    PolicyModel response = new PolicyModel();
    User currentUser = await Repositories.User.GetUserDetailsAsync(id);

    if(currentUser.IsNew)
    {
        await HandleDeliveriesAsync(await Repositories.Delivery.GetAvailableDeliveries());
    }
    ...
    return response;   
}

public async Task HandleDeliveriesAsync(IEnumerable<Delivery> deliveries)
{
    if(deliveries == null || deliveries.Count() == 0
    {
        throw new Exception("no deliveries available");
    }
    response.Deliveries = deliveries;
    Ienumerable<Line> lines = await Repositores.Delivery.GetActiveLinesAsync();
    lines.AsParallel().ForAll(line => {
    await Repositories.Delivery.AssignLineAsync(line,currentUser);   
}
公共异步任务GetPolicyAsync(int-id) { PolicyModel响应=新的PolicyModel(); User currentUser=await Repositories.User.GetUserDetailsAsync(id); if(currentUser.IsNew) { wait HandleDeliveriesAsync(wait Repositories.Delivery.GetAvailableDeliveries()); } ... 返回响应; } 公共异步任务HandleDeliveriesAsync(IEnumerable交付) { if(deliveries==null | | deliveries.Count()==0 { 抛出新异常(“无可用交付”); } 响应。交付=交付; Ienumerable lines=wait Repositores.Delivery.GetActiveLinesAsync(); lines.AsParallel().ForAll(line=>{ wait Repositories.Delivery.AssignLineAsync(line,currentUser); }
不要使用
Task.Factory.StartNew
Task.Delay
,因为它只是将相同的工作卸载到不同的线程。在大多数情况下,它不会增加任何价值,实际上在ASP.Net中也会造成损害。

经过大量搜索,我发现了这篇文章:

它解释了@i3arnon在评论中说的话。根本没有工人,线程正在做所有的工作。
简而言之,处理web请求的线程到达一个设计为在驱动程序堆栈上异步完成的端口,它创建一个请求并将其传递给驱动程序。
驱动程序将其标记为挂起并报告“完成”返回到线程池以获得另一个分配的线程。
实际作业不是由线程完成的,而是由驱动程序完成的,该驱动程序借用所有线程的cpu时间,让它们自由处理业务。
当操作完成后,驱动程序通知它,一个可用线程将继续

因此,从中我了解到,我应该研究每一个异步方法,并检查它是否实际执行异步使用驱动程序的操作

要想一想:网站的可扩展性取决于真正以异步方式完成的机会的数量,如果你没有任何机会,那么你的网站将无法扩展

版主们,我是一个真正的新手,如果我完全弄错了,请纠正我
谢谢!

这里没有“worker”。一个真正的
async
操作不需要任何东西来“运行”。你是在问用同一种方法多次使用
wait
是否合适吗?如果是的话,那么是的。除此之外,如果你打开Web API框架源代码,你可以看到