【问题标题】:Running Multiple Tasks parallely results in System.AggregateException并行运行多个任务会导致 System.AggregateException
【发布时间】:2023-03-16 21:45:01
【问题描述】:

我正在从具有不同数据集标识符的 API 中获取数据作为查询参数。早些时候我尝试了一种同步方法,但它花费了太多时间。所以我决定在 foreach 循环中为每个数据集标识符动态创建任务。这是我写的代码

foreach (var dataset in datasets)
{
    Task task = new Task(() =>
    {
        using (var client = new HttpClient())
        {
            var urlParameters = $"?apikey={apiKey}&dataset={dataset}";
            client.BaseAddress = new Uri(url);
            HttpResponseMessage response = client.GetAsync(urlParameters).Result;
            var yearlyDatasetResult = response.Content.ReadAsStringAsync().Result;
            var datasetCsvHeader = yearlyDatasetResult.Split(new[] { '\r', '\n' })
                .FirstOrDefault();
            var headers = datasetCsvHeader.Split(';');
            if (csvHeaders.Length < headers.Length)
                csvHeaders = headers;

            var content = yearlyDatasetResult.Substring(datasetCsvHeader.Length);
            using (var file = new StreamWriter("C:\\xxxx\\xxxx\\source\\"
                + $"repos\\xxxx\\CSV\\{dataset}.csv"))
            {
                file.WriteLine(content);
            }
        }
    });

    task.Start();
    tasksToWait.Add(task);
}

Task.WaitAll(tasksToWait.ToArray());
Console.WriteLine("All tasks completed");

我的目标是获取所有 CSV 文件,然后通过并行运行的任务在没有标题的情况下写入我的系统,但我得到了System.AggregateException。可能是因为这条线的阻塞性质吗?

HttpResponseMessage response = client.GetAsync(urlParameters).Result;

我无法猜测这种异常的原因,我知道其中一项任务失败了,这就是为什么我会收到这个聚合异常,这就是 Task.WaitAll(...) 的本质,可能的情况是什么解决方案?

【问题讨论】:

  • 一个 AggregateException 应该包含一个或多个其他异常,这些异常可以准确地告诉您问题出在哪里,但是,是的,我猜这是阻塞调用以及您甚至没有 await 的事实Task.WaitAll。你真的应该承诺使用 async/await。
  • 此行执行过程中发生异常? HttpResponseMessage response = client.GetAsync(urlParameters).Result;
  • @RichárdBaldauf 我只是猜测,即使我也不确定
  • @ShubhamTiwari 啊,好吧。为了弄清楚这一点,我建议克里斯托弗在下面回答。使用 async/await 功能有助于识别异常的来源^.^

标签: c# multithreading asynchronous task


【解决方案1】:

并行运行多个任务会导致 System.AggregateException

这是一个稍微不正确的评估。您的代码正在抛出异常。 AggregateException 只是在那里,所以您不会意外忽略它们。

众所周知,多任务处理异常擅长处理异常。由于这是沟通它们的唯一方式,因此执行行中的每个任务都可能抛出异常,并且永远不应忽略异常,所有异常都会被收集并整齐地包装到 AggregateException 中。

你的目标是弄清楚这些异常是什么,正确地classify them,然后是properly handle them。没有内在的例外很难说

【讨论】:

    【解决方案2】:

    AggregateException 只是一个包含其他异常的包。您可以通过属性InnerExceptions 访问这些异常:

    try
    {
        Task.WaitAll(tasksToWait.ToArray());
        Console.WriteLine("All tasks completed");
    }
    catch (AggregateException aex)
    {
        foreach (var ex in aex.Flatten().InnerExceptions)
        {
            Console.WriteLine(ex);
        }
    }
    

    在上面的例子中,我使用了Flatten的方法,以防万一有嵌套的AggregateExceptions,来展平树。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多