【问题标题】:Async for Long operation with HttpResponseMessage使用 HttpResponseMessage 进行长操作的异步
【发布时间】:2018-01-20 20:59:59
【问题描述】:

我正在计算我的 C# web api 的性能。我写了一个很简单的HelloWorld回复:

public class HelloWorldController : ApiController
{
    public HttpResponseMessage Get()
    {

        return new HttpResponseMessage()
        {
            Content = new StringContent("HelloWorld")
        };
    }
}

我使用JMeter 进行了测试,我设置了 1000 个用户请求,它运行良好(CPU 使用率高达 100%)。但问题是,当 api 的操作时间较长时,响应变得更糟,每个响应只有 3 个(CPU 使用率

public HttpResponseMessage Get()
    {
        Thread.Sleep(1000);
        return new HttpResponseMessage()
        {
            Content = new StringContent("HelloWorld")
        };
    }

在谷歌之后,我想出了使用异步的想法,但我仍然遇到了同样的问题。我不知道问题是什么或我的代码实现。下面是我的示例实现。

public async Task<HttpResponseMessage> Get()
    {
        return new HttpResponseMessage()
        {
            Content = new StringContent(await LongOperationAsync())
        };
    }
    private string LongOperation()
    {
        //long operation here
        Thread.Sleep(1000);
        return "HelloWorld";
    }

    private Task<string> LongOperationAsync()
    {
        return Task.Factory.StartNew(() => LongOperation());
    }

有人知道问题是什么或对此问题有任何想法吗?

【问题讨论】:

  • 你认为Thread.Sleep(1000);实际上在这里做什么?

标签: c# asynchronous iis asp.net-web-api async-await


【解决方案1】:

asyncawait 不是“mak teh codez moah awesomz”的灵丹妙药。 On ASP.NET, await enables your application to be more scalable (and respond to changes in scale more quickly) by making optimum use of the thread pool.

因此,如果您正在释放一个线程池线程 (await) 但使用了另一个线程池线程 (StartNew),您将不会获得任何收益。特别是exposing a fake-async method for a synchronous API is an antipattern

如果可能,最好的解决方案是让LongOperationAsync 成为自然异步操作:

public async Task<HttpResponseMessage> Get()
{
  return new HttpResponseMessage()
  {
    Content = new StringContent(await LongOperationAsync())
  };
}

private async Task<string> LongOperationAsync()
{
  //long operation here
  await Task.Delay(1000);
  return "HelloWorld";
}

如果这是不可能的,那么您最好保持同步。使用Task.Run(或even worseStartNew)根本没有帮助。

【讨论】:

    【解决方案2】:

    方法 LongOperationAsync 和 LongOperation 也应该是 async

    private async Task<string> LongOperation()
    {
        //long operation here
        await Task.Delay(1000);
        return "HelloWorld";
    }
    private async Task<string> LongOperationAsync()
    {
        var rt =  await Task.Run(() => LongOperation());
        return rt;
    }
    

    见: Asynchronous programming

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-20
      • 2016-02-09
      • 1970-01-01
      • 2017-09-09
      • 2011-07-02
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      相关资源
      最近更新 更多