C# 使用异步任务提高HttpResponseMessage性能

C# 使用异步任务提高HttpResponseMessage性能,c#,asp.net,.net,async-await,C#,Asp.net,.net,Async Await,我在C#Framework 4.7.2 API的控制器中实现了一种方法,该方法必须是异步的,才能解除重进程的线程阻塞(如文章中所述),以便服务可以继续服务来自其他客户端的请求,并在该进程完成时返回响应 [HttpGet] [Route("Method")] public async Task<HttpResponseMessage> Method() { HttpResponseMessage task = awai

我在C#Framework 4.7.2 API的控制器中实现了一种方法,该方法必须是异步的,才能解除重进程的线程阻塞(如文章中所述),以便服务可以继续服务来自其他客户端的请求,并在该进程完成时返回响应

    [HttpGet]
    [Route("Method")]
    public async Task<HttpResponseMessage> Method()
    {
        HttpResponseMessage task = await Task.Run(() =>
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            // response.Content...
            return response;
        });
        return task;
    }
[HttpGet]
[路线(“方法”)]
公共异步任务方法()
{
HttpResponseMessage任务=等待任务。运行(()=>
{
HttpResponseMessage response=新的HttpResponseMessage(HttpStatusCode.OK);
//回应。内容。。。
返回响应;
});
返回任务;
}

我决定使用异步方法的原因是为了提高性能。还有其他可能的解决方案吗?

您误解了该指南

您的方法是同步的,
Task.Run
将工作卸载到线程池线程,从而有效地模拟异步行为

在ASP.Net上下文中,该线程来自用于服务其他请求的池,因此,当您取消阻止当前线程并将其释放回池中时,您是在借用另一个线程来执行该工作

这种线程切换不会使更多的线程可用,但会引入不必要的开销

解决办法是什么


嗯,删除对
Task.Run
的调用将略微提高性能,但是如果您的服务确实遇到吞吐量问题,您可以将请求持久化到队列中,以便由另一个进程拾取,允许您的
方法
提前返回并保持API响应。

考虑到您的代码执行是同步的,因此将其标记为异步可能没有多大意义

但是,如果即使对于同步操作也必须有异步端点,则可以使用
wait Task.FromResult(resultObject)
或其无效变量
等待任务。CompletedTask
。这将使您的代码类似于:

[HttpGet]
[Route("Method")]
public async Task<HttpResponseMessage> Method()
{
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    // response.Content...        
    return await Task.FromResult(response);
}
[HttpGet]
[路线(“方法”)]
公共异步任务方法()
{
HttpResponseMessage response=新的HttpResponseMessage(HttpStatusCode.OK);
//回应。内容。。。
返回等待任务。FromResult(响应);
}

还有更多详细信息

我正在使用Task.Run,因为在Task中运行的代码是同步的,所以我无法执行其他等待操作。你能用放置在那里的实际代码替换
//response.Content…
注释吗?@TheodorZoulias我认为这与此无关,只有对生成返回给客户端的文档的第三方库的调用。这些第三方库如何与实例交互?这里有些奇怪。谢谢你的回答。约翰纳森·巴克利,我误解了那个指南。您提出的解决方案对我来说似乎很好,但是如果所有线程都很忙,并且有更多的请求进入服务,那么排队也可能会影响响应时间。这个问题还有其他可能的解决方案吗?我将重新表述这个问题,以帮助更多处于这种情况的人。@david.q:如果一个线程正在处理一个请求,那么其他线程可以处理其他请求。ASP.NET默认是多线程的,因此除非线程池中的请求太多,否则不会在那里排队。感谢您的评论@Stephen Cleary,那么除了使请求更轻,这样线程就不会被阻止并可以服务更多的客户之外,没有其他可能,对吗?顺便说一句,感谢您在指南和博客上所做的工作,我发现它非常有用。@david.q:CPU密集型web服务是不寻常的,因此调整ASP.NET线程池设置可能会有所帮助。但归根结底,CPU密集型web服务在一台机器上无法很好地扩展,您需要扩展以服务更多的客户。