我刚刚在DevLabs上下载了.NET 3.5 SP1的Parallel Extensions并开始使用它。一切似乎工作正常,直到我注意到日志中有一些例外,我很难理解它们为什么会发生。
以下是并行任务的片段:
Parallel.ForEach(myJobArray, currentJob =>
{
JobElements myJobElements = GetJobElements(currentJob);
Parallel.For(0, myJobElements.Length, (currentIndex, loopState) =>
{
if (MyFunction(param1, myJobElements[currentIndex]))
{
loopState.Stop();
}
}
);
}
);
这是MyFunction的伪代码:
private bool MyFunction(MyObject1 param1, MyObject2 param2)
{
log(string.Format("start SubFunction1() from thread {0}", Thread.CurrentThread.ManagedThreadId));
SubFunction1(); //which uses System.Diagnostics.Process to start a batch file (.bat) to execute a Perl script. If successful, a file will be generated.
log(string.Format("end SubFunction1() from thread {0}", Thread.CurrentThread.ManagedThreadId));
log(string.Format("start SubFunction2() from thread {0}", Thread.CurrentThread.ManagedThreadId));
SubFunction2(); //which again, uses System.Diagnostics.Process to start another batch file (.bat) to execute a Perl script which transforms the file from step #1 to a new file.
log(string.Format("end SubFunction2() from thread {0}", Thread.CurrentThread.ManagedThreadId));
}
日志显示一个线程启动了SubFunction1()但从未完成;也就是说,没有日志条目说“end SubFunction1()”具有相同的线程ID。实际上,同一个线程似乎转移到数组中的下一个作业并再次调用SubFunction1()。当另一个线程试图让前一个线程启动SubFunction2()并且找不到从SubFunction1()生成的文件时发生异常。
我认为每个线程都保证从头到尾完成任务,我无法弄清楚为什么日志会以这种方式显示。我还要补充说,行为不一致;也就是说,程序运行的大部分时间没有例外,但有时由于上述问题而抛出异常。
有什么想法吗?
答案 0 :(得分:0)
我认为每个线程都保证从头到尾完成任务,我无法弄清楚为什么日志会这样显示。
如果SubFunction1()
抛出异常,则不会发生这种情况。
答案 1 :(得分:0)
我认为每个线程都保证从头到尾完成任务 完成,我无法弄清楚为什么日志显示这种方式
首先,由于您使用的是loopState.Stop();
,因此无法保证,并且您的代码中不清楚MyFunction()
返回的时间,时间和内容。
然后,做什么任务/线程以及写入日志(文件)的内容是两回事,而不是相互反映:
log(string.Format("end SubFunction1() from thread {0}", Thread.CurrentThread.ManagedThreadId));
不显示实际任务的线程ID(但是日志的线程)。如果它确实显示了实际任务的线程ID,那么就不清楚(从你的代码中)为什么你没有通过从多个线程写入日志来获得跨线程异常您应该通过以下任一方式同步日志记录:
Parallel.For
循环刷新输出流中的锁来保护记录