【问题标题】:More than one await in HttpTaskAsyncHandlerHttpTaskAsyncHandler 中不止一个 await
【发布时间】:2013-05-08 15:45:25
【问题描述】:

HttpTaskAsyncHandler 是一个很好的基类,用于在 ASP.NET 4.5 中制作异步 http 处理程序 我想知道运行时如何处理 ProcessRequestAsync 中的多个 await 语句。

public class CallbackHandler : HttpTaskAsyncHandler
{
    public override async Task ProcessRequestAsync(HttpContext context)
    {
        int value1 = await Task.Factory.StartNew(() => 1);
        int value2 = await Task.Factory.StartNew(() => 2);
        int value3 = await Task.Factory.StartNew(() => 3);

        context.Response.Write(value1 + value2 + value3);
    }

    public override bool IsReusable
    {
        get { return true; }
    }
}

IIS 线程是否被搁置了 3 次? 我最终如何测试/查看这个? 将 3 个 await 包装在 async 方法中会更好吗?

编辑: 我担心这段代码需要 IIS-workerthread 4 次来处理这个请求。 如果我将它包装在一个异步方法中 - 它会表现得更好吗?

MSDN article

这是解释 ASP.NET 中同步和异步页面处理之间差异的图表。恐怕我的示例会导致从主工作线程(图中的粉红色框)启动 3 个线程,从而增加开销。

IIS -> task1 TP -> IIS -> task2 TP -> IIS -> task3 TP -> IIS

(任务切换到主IIS WT 4次)

或者是编译器非常聪明,它只是从一个任务传递到下一个任务,并在 3 个任务完成后返回主线程。

IIS -> task1 TP -> task2 TP -> task3 TP -> IIS

(任务切换到主IIS WT 1次)

【问题讨论】:

  • 您的担忧是有效的,因为文档没有说明任何内容。我自己从未使用过它,因为我最近没有进行任何 Web 开发,但是,由于正在传递一个 HttpContext 实例,因此您可能不在工作线程上。如果你是,是的,你会来回走动。您可以检查当前的同步上下文。如果它不为 null,则您在工作线程上。

标签: asp.net async-await


【解决方案1】:

它处理得很好。

在 IIS 中,您有一个“请求上下文”提供给您的 async 处理程序,默认情况下您的 async 方法将在该上下文中恢复。每当您 await 一个未完成的任务时,线程将返回到线程池(它没有被阻塞),当该任务完成时,线程池线程用于在进入该请求上下文后继续该 async 方法。

因此,没有线程被“保留”,但请求本身被“保留”。将多个awaits 放在另一个async 方法中不会有任何区别,但是启动多个Tasks 然后等待它们全部完成会有所不同,例如await Task.WhenAll(task1, task2, task3);(假设它们当然,它们都是独立的)。

我不知道验证这种行为的好方法。

【讨论】:

  • 感谢您的回答,但我担心此代码需要 IIS 工作线程 4 次才能处理此请求。如果我将它包装在一个异步方法中 - 它会表现得更好吗?
  • 我不确定您所说的“4 次”是什么意思;你能换一种说法吗?将其包装在 async 方法中不会使其性能更好。
猜你喜欢
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
相关资源
最近更新 更多