PLINQ 查询中的计算顺序是什么

本文关键字:顺序 是什么 计算 查询 PLINQ | 更新日期: 2023-09-27 18:34:02

下面是我在Windows服务中定期运行的示例PLINQ查询:

var resultList = new List<Task<SendMailResult>>();
try
{
    resultList = emailsToSend
        .AsParallel().WithDegreeOfParallelism(10)
        .Select(async e =>
        {
            bool bSuccess = false;
            if (await MailHelper.SendMailAsync(e.sTo, e.sSubject, e.sHTML) == true)
            {
                bSuccess = true;
            }
            return new SendMailResult
            {
                succeeded = bSuccess,
                resultid = e.id
            };
        }).ToList();
    Task.WaitAll(resultList.ToArray());
}
catch (AggregateException aggEx)
{
    foreach (var ex in aggEx.InnerExceptions)
        Console.Out.WriteLine(ex.Message);
}

我的问题是 - 如果要在内部匿名async Func<EmailToSend, Task<SendMailResult>>中抛出异常(在调用 MailHelper.SendMailAsync() 时,很可能),因此将调用 AggregateException 处理程序 - 是否会在任何时候调用以下.ToList()

换句话说,是否有可能某些任务成功完成,直到一个任务没有成功完成,并且在 AggregateException 处理程序中捕获后遵循下面的代码片段,我可能有一个非 0 计数的结果列表?或者异常是否意味着永远不会调用 ToList(),并且如果抛出异常,结果列表将始终为空?

意识到我正在使用这种多线程力量与鲨鱼一起游泳,而没有完全理解它的含义。因此问题来了!谢谢。

PLINQ 查询中的计算顺序是什么

由于懒

Select .ToList()将在任何时候被调用,结果列表将包含所有任务。
执行将从.ToList()方法调用开始。 Select将仅提供可以枚举列出IEnumerable
如果某些任务异常失败,您将捕获它们,毕竟您将获得任务列表,其中某些任务将具有Faulted状态。

编辑:
异常引发将由Task.WaitAll方法调用触发,因此列表将在之前创建,并将确切的项目计为初始集合。

更新:
关于Task.WaitAll内部结构:
如果你想知道它是如何工作的,你可以看看源代码。
首先,它收集所有未完成的任务,然后等待这些任务完成。
之后,它从所有任务中收集所有内部异常,然后将其作为单个AggregateException