繁体   English   中英

不等待所有任务是否安全

[英]Is it safe not to wait for all tasks

假设我有以下操作方法:

[HttpPost]
public async Task<IActionResult> PostCall()
{
    var tasks = new List<Task<bool>>();
    for (int i = 0; i < 10; i++)
        tasks.Add(Manager.SomeMethodAsync(i));

    // Is this line necessary to ensure that all tasks will finish successfully?
    Task.WaitAll(tasks.ToArray());

    if (tasks.Exists(x => x.Result))
        return new ObjectResult("At least one task returned true");
    else
        return new ObjectResult("No tasks returned true");
}

Task.WaitAll(tasks.ToArray())必须确保所有任务都能成功完成? Exists 无法访问其Result的任务是否会成功完成后台执行? 或者有些任务(没有等待)会被删除,因为它们不会附加到请求中吗? 有没有更好的实施我错过了?

是的,除非等待它们(等待等待的东西),否则不保证任务完成

在您的情况下,您应该进行的主要更改是创建Task.WaitAll

await Task.WhenAll(tasks);

所以它实际上是异步的。 如果你只是想等待一个任务返回,使用WhenAny代替。

在您提供的实现下, Task.WaitAll调用阻止调用线程,直到所有任务都完成。 它只会进入下一行,并在发生这种情况后执行Exists检查。 如果删除Task.WaitAll ,则Exists检查将导致调用线程按顺序阻塞每个任务; 即它首先阻止tasks[0] ; 如果返回false,则会阻塞tasks[1] ,然后阻塞tasks[2] ,依此类推。 这是不可取的,因为如果任务完成无序,它不允许您的方法提前完成。

如果您只需要等到任何一个任务首先返回true,那么您可以使用Task.WhenAny 这将使任何任务完成后您的异步方法恢复。 然后,您可以检查它是否评估为true并立即返回成功; 否则,您将继续重复剩余任务集的过程,直到没有剩余任务为止。

如果您的代码作为应用程序(WPF,WinForms,Console)运行,那么剩余的任务将继续在线程池上运行直到完成,除非应用程序关闭。 线程池线程是后台线程,因此如果所有前台线程都已终止(例如因为所有窗口都已关闭),它们将不会使进程保持活动状态。

由于您运行的是Web应用程序,因此您可能会在任务完成之前回收应用程序池。 未完成的任务是即发即弃的,因此运行时未被跟踪。 为了防止这种情况发生,您可以通过HostingEnvironment.QueueBackgroundWorkItem方法在运行时注册它们,如注释中所示。

[HttpPost]
public async Task<IActionResult> PostCall()
{
    var tasks = Enumerable
        .Range(0, 10)
        .Select(Manager.SomeMethodAsync)
        .ToList();

    foreach (var task in tasks)
        HostingEnvironment.QueueBackgroundWorkItem(_ => task);

    while (tasks.Any())
    {
        var readyTask = await Task.WhenAny(tasks);
        tasks.Remove(readyTask);
        if (await readyTask)
            return new ObjectResult("At least one task returned true");
    }

    return new ObjectResult("No tasks returned true");
}

暂无
暂无

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

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