.net 这对Parallel.ForEach安全吗?

.net 这对Parallel.ForEach安全吗?,.net,task-parallel-library,parallel.foreach,.net,Task Parallel Library,Parallel.foreach,我有一个服务,可以提取电子邮件进行解析。每封电子邮件都由多个访问者解析(所有访问者都使用一种方法实现了一个简单的IEmailVisitor接口:void-Visit(visitableMail-email)。对于某些背景上下文,访问者实现包括SubjectVisitor、BodyVisitor、SummaryVisitor等 该服务有一个IList,它在启动时创建一次,然后以这种方式在计时器事件中重新使用: foreach (var email in emailsToParse) { f

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

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

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

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

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

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


我的访问者中没有人在调用访问之间保持状态(此)

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

如果此方法使用的外部对象不是线程安全的,那么要么使其成为线程安全的,要么不使用并行


如果一次访问没有影响到另一次访问,那么您可能最好选择并行访问。

我将把我自己的问题标记为已解决,因为从一些评论中可以清楚地看出,问题的核心不是并行的
parallel.ForEach()本身,但在考虑多线程时,你必须考虑所有的问题。TPL当然提供了更简单的结构,但是你仍然需要知道你在做什么。时间要多学习一些。

“我的访问者中没有一个在访问的调用之间保持状态”。。现在,由于正在并行调用Visit方法,因此无法使用上述语句来确定它是否安全。您需要提供Visit方法内部发生的情况。如果所有Visit都设置了VisitableEmail的属性,并且IEmailVisitor上没有任何更改,则您是安全的。例如,如果您正在设置类似VISII的内容tor.EmailScont等。然后您可能会遇到问题。“我的访问者中没有一个在调用访问之间保持状态(此)。”它如何在该方法的单个调用中保持状态?它是否使用字段进行此操作?大多数访问者都会获得解析列表(常规)来自数据库的表达式,但一旦设置,此列表是不可变的,并且对于所有被访问的电子邮件都是相同的。svick(和cheedep),我想我明白你现在在问什么了。简短的回答是否定的:状态保存在电子邮件本身。例如,
BodyVisitor
有一个私有函数
ParseRatings
,它接收电子邮件并可能设置其评级。从本质上说,电子邮件保存其自身的所有状态,并在访问者之间逐渐建立.