代码之家  ›  专栏  ›  技术社区  ›  ShaneKm

在等待任务中隔离异常。whenall()

  •  1
  • ShaneKm  · 技术社区  · 6 年前

    执行task.whenall()时隔离异常的正确方法是什么?这样,当一个进程(用户)抛出异常时,其他进程将继续处理。

    try
    {
        var usersToProcess = new List<User>();
    
        var processes = new List<Task>();
        foreach (var user in usersToProcess)
        {
            var process = // Set up here
            processes.Add(_processHandler.Process(process));
        }
    
        await Task.WhenAll(processes); // await all here
    }
    catch (Exception ex)
    {
        throw ex;
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Rahul Tripathi    6 年前

    所有任务都将并行运行,因此即使一个任务抛出异常,它也不会停止其他任务以停止执行见 docs :

    将Task.WhenAll方法应用于任务集合这个 WhenAll的应用程序返回一个在 集合中的每个任务都已完成任务似乎在运行 并行,但不创建其他线程任务可以 按任何顺序完成。

        2
  •  1
  •   mm8    6 年前

    await Task.WhenAll(processes) 将等待所有收入 processes 完成并抛出任何任务引发的第一个异常。因此,当您到达catch处理程序时,所有任务都将完成或抛出。

    您可以通过使用计数器变量来确认这一点:

    int count = 0;
    try
    {
        var usersToProcess = new List<User>();
    
        const int n = 10;
        var processes = new List<Task>();
        for (int i = 0; i<n; ++i)
        {
            int j = i;
            processes.Add(Task.Run(() =>
            {
                Thread.Sleep(1000);
                Interlocked.Increment(ref count);
    
                //throw an exception in task 2 and 5
                if (j == 1 || j == 4)
                    throw new Exception("...");
            }));
        }
    
        await Task.WhenAll(processes); // await all here
    }
    catch (Exception ex)
    {
        Console.WriteLine(count); //will always print 10
    }
    
    Console.WriteLine(count); //will always print 10
    

    中的任务总数 过程 将始终在上述示例代码中打印到控制台,而不管是否有任何任务引发。