加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – PLINQ查询中的评估顺序是什么?

发布时间:2020-12-15 22:26:49 所属栏目:百科 来源:网络整理
导读:下面是我在 Windows服务中定期运行的PLINQ查询示例: var resultList = new ListTaskSendMailResult();try{ resultList = emailsToSend .AsParallel().WithDegreeOfParallelism(10) .Select(async e = { bool bSuccess = false; if (await MailHelper.SendMa
下面是我在 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);
}

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

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

我意识到我正在和鲨鱼游泳,使用这种多线程的力量而不完全了解它的含义.因此问题!谢谢.

解决方法

由于Select laziness,任何时候都会调用.ToList(),结果列表将包含所有任务.
执行将以.ToList()方法调用开始. Select将仅提供可枚举的IEnumerable列表.
如果某些任务会因异常而失败,您将捕获它们,毕竟您将获得任务列表,其中某些任务将具有“故障”状态.

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

更新:
关于Task.WaitAll内部结构:
如果你想知道它是如何工作的,你可以看看source code.
首先是collects all incompleted tasks然后是waits,完成这些任务.
之后它从所有任务中获取collects all inner exceptions,然后将其作为单个AggregateException引发.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读