我有一个拉电子邮件进行解析的服务。每个电子邮件都由多个访问者解析(所有访问者都使用一种方法实现简单的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>
答案 0 :(得分:2)
我的访问者都没有在访问(这个)的调用之间保持状态
如果这是真的,那么它似乎是一种安全的操作。
如果此方法使用的东西不是线程安全的,那么要么使其线程安全,要么不使用并行。
如果一次访问不会对另一次访问产生影响,那么你可能会很平行。
答案 1 :(得分:0)
我要将自己的问题标记为答案,因为从一些评论中可以清楚地看出,问题本身并不是Parallel.ForEach()
本身,而是考虑到多个问题时你必须考虑的问题。穿线。 TPL当然提供了更简单的结构,但你仍然需要知道你在做什么。是时候学习更多了。