这对Parallel.ForEach来说是否安全?

时间:2013-05-20 17:00:16

标签: .net task-parallel-library parallel.foreach

我有一个拉电子邮件进行解析的服务。每个电子邮件都由多个访问者解析(所有访问者都使用一种方法实现简单的IEmailVisitor接口:void Visit(VisitableEmail email)。对于某些背景上下文,访问者实现包括SubjectVisitor,BodyVisitor,SummaryVisitor等。

该服务有IList<IEmailVisitor>,它在启动时创建一次,然后以这种方式在计时器事件中重用:

foreach (var email in emailsToParse)
{
    foreach (var visitor in _visitors)
    {
        email.Accept(visitor);
    }
}

电子邮件类具有以下方法:public void Accept(IEmailVisitor visitor) { visitor.Visit(this);}当访问每个访问者时,将在电子邮件实例本身上设置(或更改)属性。

可能会有不少要处理的电子邮件。我的问题是,我是否可以安全地将上述代码转换为:

Parallel.ForEach(emailsToParse, email =>
{
    foreach (var visitor in _visitors)
        email.Accept(visitor);
});

我的访问者都没有在Visit(this)的调用之间保持状态。我确信这个问题反映了我对任务并行性的相当肤浅的了解,但是尽管我一直在做的阅读,我不确定这是否是一种安全的方法(假设每次都有足够的电子邮件来证明操作的合理性)。 / p>

2 个答案:

答案 0 :(得分:2)

  

我的访问者都没有在访问(这个)的调用之间保持状态

如果这是真的,那么它似乎是一种安全的操作。

如果此方法使用的东西不是线程安全的,那么要么使其线程安全,要么不使用并行。

如果一次访问不会对另一次访问产生影响,那么你可能会很平行。

答案 1 :(得分:0)

我要将自己的问题标记为答案,因为从一些评论中可以清楚地看出,问题本身并不是Parallel.ForEach()本身,而是考虑到多个问题时你必须考虑的问题。穿线。 TPL当然提供了更简单的结构,但你仍然需要知道你在做什么。是时候学习更多了。