use*_*er1 2 c# parallel-processing foreach exception-handling
我有一个Parallel.Foreach
下载文件的循环:
try
{
var parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 8;
int failedFiles = 0;
Parallel.ForEach(FilesToDownload, parallelOptions, tile =>
{
bool downloaded = DownloadTile(File);
if (downloaded)
{
//Downloaded :)
}
else
{
failedFiles++;
if (failedFiles > 10)
{
throw new Exception("10 Files Failed to download. Failing download");
}
}
parallelOptions.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (Exception ex)
{
throw; //This throws it up to a main method that cancels my program
}
Run Code Online (Sandbox Code Playgroud)
我想知道Exception
从Parallel.Foreach
方法内部抛出一个正确的方法是什么?在我的实例中,我认为一旦抛出第一个异常,我将看到抛出异常8次.
在Parallel.ForEach
循环中抛出异常的正确方法是什么?
首先,更好地使用Interlocked.Increment(ref failedFiles)
而不是failedFiles++
.否则可能会发生10-15次失败,但由于缺少缓存同步和编译器/抖动优化的影响,最终会得到一个值为7-8的计数器.您的程序循环可能会抛出更多异常,但最后它将聚合为一个异常AggregateException
,并且outter catch()
将接收该单个异常实例.如果您不想要更多例外,则AggregateException
可以使用==
而不是>
if (Interlocked.Increment(ref failedFiles) == 10)
Run Code Online (Sandbox Code Playgroud)
当在循环内抛出异常,Parallel.ForEach
阻止其他迭代启动时,它等待当前正在运行的迭代完成,然后它聚合它捕获的所有异常,将其打包AggregateException
并抛出该单个实例.这意味着在您的情况下,单个例外将阻止进一步下载.