0

这实际上是我自己的一个问题,以回应我对具有横切关注的循环依赖的回答

是否有一种变体Parallel.ForEach至少可以保证无论任何特定任务是否引发异常 ,至少都会尝试每个可能的任务?

我意识到我可以将每个任务包装在它自己的try/ catch/finally等(直接或间接)中,并且可能使用一些同步容器来保存异常或其他东西,但这似乎需要做很多工作——有许多可能的解决方案来评估--work 我认为Task Parallel 库处理起来可能会更好。

我在任务中抛出异常的试验似乎表明这Parallel.ForEach可能会在中间中止并取消任何剩余的任务)。情况似乎与{some enumerable}.AsParallel().ForAll({the task});. 我认为中止剩余任务的策略 - 或者在创建剩余任务之前中止,可能是 - 在某些情况下是完全可以接受的行为。然而,有时任务会死掉,我们最好尝试运行尽可能多的任务,并跟踪哪些任务幸存,哪些任务死亡。

我看到了使用任务并行库时如何处理所有未处理的异常?但我不清楚这是否能回答我的问题。

http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx <= 也可能是相关的。

这对我来说不是任何高优先级的问题,我只是想我会把它扔在那里,以防其他人可能想要提供答案。

编辑:以防万一代码中确实存在演示行为的错误,这里是(也与另一个问题有关)。我一直在 LinqPad 中运行它,有时我看到所有WriteLine结果,有时我没有。请不要批评代码质量,我只是想看看我是否理解正在发生的事情。[ThreadStatic]我怀疑该修改后的变量可能存在某些问题。

static void Main() //Main(string[] args)
{
    string[] messages = "this is a test.  but it's going to be an issue!".Split(' ');

    try{
        messages.AsParallel().ForAll(Log);
    } catch(AggregateException){
        throw;
    }

    Console.ReadLine();
}
[ThreadStatic]
static bool _disable = false;
public static void Log(string message)
{
    if (_disable)
    {
        return;
    }
    try {
        _disable = true;
        Console.WriteLine(GetPrefix() + message);
        throw new Exception("bar");
    } finally {
        _disable = false;
    }
}

public static string GetPrefix()
{
    Log("Getting prefix!");
    return "Prefix: ";
}
4

1 回答 1

1

首先,我认为当您谈论任务时会令人困惑。您所拥有的是循环的迭代,它将使用Tasks 并行执行,但这并不意味着每次迭代都是一项任务。

其次,如果您真的只是为了日志记录而这样做,那么您不太可能获得任何性能提升,我认为日志记录不是可并行化的。

现在,您可以做的是为Task循环的每次迭代手动创建一个单独的,然后等待它们完成使用Task.WaitAll(). 这样,所有迭代都将被执行,如果其中一些失败,WaitAll()将抛出一个AggregateException包含它们的所有迭代。

var tasks = messages.Select(m => Task.Factory.StartNew(() => Log(m)));
Task.WaitAll(tasks.ToArray());

这可能会比Parallel.ForEach()PLINQ 效率低,但这对您来说可能没问题。如果没有,那么您必须使用您建议的try-方法。catch

于 2013-07-19T01:50:25.700 回答