繁体   English   中英

异步方法中的 Task.Run() 导致线程池饥饿?

[英]Task.Run() in async method causes thread pool starvation?

我的 .netcore 应用程序中有这段代码

[HttpPost]
[Route("doSomething")]
public async Task<IActionResult> DoSomethingAsync([FromBody] Input input)
{
    // Do Something
    var task1 = Task.Run(async () => 
    {
        await taskFactory.DoTask(input);
    });

    // Do Something Differently
    var task2 = Task.Run(async () => 
    {
        await taskFactory.DoAnotherTask(input);
    });

    await Task.WhenAll(task1, task2);

    return Accepted();
}

DoTask()DoAnotherTask()都是相互独立的,可以并行执行,但必须等待它们都处于完成状态。

因此,我创建了两个任务并使用Task.WhenAll()等待它们。

但是我有一个评论评论不要在async方法中使用Task.Run() ,因为它可能导致线程池饥饿。

问题 1:我的代码如何导致线程池饥饿?
问题2:如果导致线程池饥饿,我该如何并行运行这两个任务?

对于您的线程池饥饿问题,如果您运行一个已经是异步的任务,则使用 task.run 执行 2 个新任务,并且在其中运行 2 个异步方法,每次调用 5 个任务,然后等待两者的完成每个请求有 6 个任务。

我通常会这样做,你仍然有 4 个任务,但最终池会持续更长时间。

[HttpPost]
[Route("doSomething")]
public async Task<IActionResult> DoSomethingAsync([FromBody] Input input)
{
    // Do Something
    var t1 = taskFactory.DoTask(input);

    // Do Something Differently
    var t2 = taskFactory.DoAnotherTask(input);


    await Task.WhenAll(t1, t2);

    return Accepted();
}

要自信地回答您的问题,我们必须了解DoTaskDoAnotherTask方法的实现。 在不知道的情况下,我们可以假设它们已正确实现并遵循异步方法的礼仪,即立即返回Task ,而不会阻塞调用线程。 在这种假设下,答案是:不,您的代码不会导致线程池饥饿。 这是因为Task.Run使用的ThreadPool线程要做的工作量可以忽略不计,它只是创建一个Task object,所以它几乎会立即返回到ThreadPool

应该指出的是,尽管使用Task.Run包装表现良好的异步委托对ThreadPool的健康影响微乎其微,但它也没有任何好处。 看看这个半相关的问题: Task.Run 在 ASP .NET MVC Web Application 中被认为是不好的做法吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM