如何使用 async/await 避免此 .NET Core Web API 中的线程池耗尽和死锁?

问题描述 投票:0回答:1

我正在开发 .NET Core Web API,在调用异步方法时遇到了性能问题和潜在的死锁。我怀疑我错误地使用了 async 和 wait 。下面是说明我的问题的代码:

public class ExampleController : ControllerBase
{
    private readonly IDataService _dataService;

    public ExampleController(IDataService dataService)
    {
        _dataService = dataService;
    }

    [HttpGet("get-data")]
    public IActionResult GetData()
    {
        var data = _dataService.GetDataAsync().Result;

        // Simulating long-running blocking operation
        Task.Delay(5000).Wait();

        return Ok(data);
    }
}

public class DataService : IDataService
{
    public async Task<List<string>> GetDataAsync()
    {
        await Task.Delay(1000); // Simulating I/O-bound work
        return new List<string> { "item1", "item2", "item3" };
    }
}

我担心的是:

我正在使用 .Result 同步调用异步方法。这会导致死锁或线程池耗尽吗? 我正在使用 Task.Delay().Wait() 来模拟长时间运行的任务。有没有更好的方法来异步处理此类延迟? 在这种情况下使用 async 和 wait 以避免死锁或线程池耗尽等性能问题的最佳实践是什么?

我尝试使用 .Result 同步调用异步方法,期望该方法返回结果而不阻塞线程。然而,应用程序遇到了性能下降,在某些情况下,它导致线程池耗尽,减慢了 API 响应时间。

c# performance asp.net-core .net-core async-await
1个回答
0
投票

我正在使用 .Result 同步调用异步方法。这会导致死锁或线程池耗尽吗?

它不应该导致服务器死锁,但可能会导致线程池耗尽。您的方法应该返回一个任务,并且可能看起来像这样

[HttpGet("get-data")]
public async Task<List<string>> GetMyData()
{
    var data = await _dataService.GetDataAsync().

    // do further processing
    return data;
}

或者使用

Task<IAsyncResult>
作为结果类型,这似乎主要是一个偏好问题。

我正在使用 Task.Delay().Wait() 来模拟长时间运行的任务。有没有更好的方法来异步处理此类延迟?

这取决于任务。如果它确实受 CPU 限制,则需要 CPU 时间来运行它,除了以某种方式优化任务之外,没有其他办法可以解决这个问题。

但是 5000 毫秒对于 Web 请求来说是非常长的 CPU 绑定时间,它们通常应该是几毫秒。有些任务确实需要那么多时间,但您需要在构建 Web 服务器和服务时牢记这一点。请注意,使用

.Wait()
并不是模拟 CPU 密集型任务的好方法,因为没有实际的 CPU 负载,因此调度程序可以在线程等待时自由运行其他线程,从而导致池耗尽。

在这种情况下使用 async 和 wait 以避免死锁或线程池耗尽等性能问题的最佳实践是什么?

  1. 等待所有返回的任务。避免
    .Result
    .Wait()
  2. 尽可能避免
    async void
    。尽可能返回任务。
© www.soinside.com 2019 - 2024. All rights reserved.