This is actually a question of my own in response to my answer to Circular dependency with cross-cutting concern
Is there a variant of Parallel.ForEach
that at least guarantees that every possible Task will at least be attempted regardless if any particular task throws an exception?
I realize I can wrap each task in it's own try
/catch
/finally
, etc, (either directly or indirectly) and maybe use some synchronized container save the exceptions, or something, but that seems like a lot of work--with many possible solutions to evaluate--work I would think might be better for the Task Parallel library to handle.
My trials of throwing exceptions within tasks seem to suggest that Parallel.ForEach
might abort in the middle and cancel any remaining tasks). The situation seems similar for {some enumerable}.AsParallel().ForAll({the task});
. I think the strategy of aborting remaining tasks -- or aborting before creating the remaining tasks, as it might be--is a perfectly acceptable behavior in some circumstances. However, sometimes, tasks are going to die, and it is best that we attempt running as many tasks as we can and keep track of which ones survived and which ones died.
I so see How to handle all unhandled exceptions when using Task Parallel Library? but its not clear to me if that answer my question.
http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx <= might also be related.
This is not any high priority question for me, I just thought I'd throw it out there just in case others might want to contribute an answer.
Edit: just in case there really is a bug in the code that demonstrates the behavior, here it is (also related to the other question). I've been running it in LinqPad, and sometimes I see all the WriteLine
results, and sometimes I don't. Please, no critiques of the code quality, I just want to see if I understand what is happening. I suspect there might be something with that [ThreadStatic]
modified variable.
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: ";
}