Parallel.ForEach在一段时间后冻结

时间:2017-08-02 14:32:48

标签: c# .net linq parallel-processing

我想使用Parallel.ForEach添加1000多个任务。以下代码用于发送电子邮件通知。问题是它只适用于大约150~200个通知&我收到了电子邮件,但之后代码被冻结了。没有收到电子邮件。

有人可以指导我朝正确的方向发展。

var exceptions = new ConcurrentQueue<Exception>();

try
{
    List<ParallelWorker_EmailNotification> workers = new List<ParallelWorker_EmailNotification>();

    foreach (Email mail in listEmails)
    {
        workers.Add(new ParallelWorker_EmailNotification(mail));
    }

    Parallel.ForEach(workers, async worker =>
    {
        try
        {
            await worker.SendNotification();
        }
        catch (Exception ex)
        {
            exceptions.Enqueue(ex);
        }
    });
}
catch (Exception ex)
{
    exceptions.Enqueue(ex);
}

1 个答案:

答案 0 :(得分:2)

var modal = document.getElementById('myModal'); var vicious = document.getElementById("vicious"); vicious.onclick = function() { modal.style.display = "none"; } 无法使用传入的异步函数,Parallel.ForEach的方法签名为async worker =>,这可能是您遇到问题的根源。 async void我们解除阻止,因为它认为工作已完成,但工作仍在后台处理,这就是您没有看到处理过的项目的原因。

最简单的解决方案(如果SendNotification是一个正确的异步函数)只是选择项目并将所有任务放入IEnumerable并等待它们。

Parallel.ForEach

如果 var exceptions = new ConcurrentQueue<Exception>(); try { var tasks = listEmails.Select(mail => new ParallelWorker_EmailNotification(mail)) .Select(async worker => { try { await worker.SendNotification(); } catch (Exception ex) { exceptions.Enqueue(ex); } }); await Task.WhenAll(tasks); } catch (Exception ex) { exceptions.Enqueue(ex); } 是一个需要一段时间才能将控制权交还给调用者的函数,那么最佳解决方案是使用TPL Dataflow进行处理。

SendNotification