I have a problem I think would be well suited towards being made parallel, but I'm not sure exactly how to express this in C#. Commonly in this program I will run an expensive test on several objects. I'm testing to make sure "I can go forward", so I need to know if any of those tests fails. However, if any test fails, the entire thing fails and the whole function should bail. In pseudo-code:
...
var guys = getGuysToProcess().ToList();
foreach (myGuys guy in guys) {
if (!guy.TestForPossibleBadness())
retur开发者_运维问答n false;
}
What pattern in C# would best let me express this and test them all in parallel? If any of these fails, the other tests should be terminated, since their result wont matter.
Since you mention TPL you also have PLINQ:
// untested
bool ok = getGuysToProcess().AsParallel().All(g => !g.TestForPossibleBadness());
As @mquan points out this might not be the most efficient. I assume the following could be faster (but I'm not 100% sure):
// untested
bool ok = ! getGuysToProcess().AsParallel().Any(g => g.TestForPossibleBadness());
The termination part could either just be to ignore the tasks, afterwards, or if possible, the usage of a CancelationToken as mentioned by mquander.
Allow me to throw out some dirty untested pseudoish code:
var guyTask = new List<Task<bool>>();
foreach(var guy in guys){
guyTask.Add(Task.Factory.StartNew(()=>guy.TestForPossibleBadness());
}
var guyTaskArr = guyTask.ToArray();
var running = true;
while(true){
var i = Task.WaitAny(guyTaskArr);
if (!guyTaskArr[i]))
foreach(var guy in guyTask){
if (!guy.IsCompleted || !guy.IsFaulted){
guy.Cancel();
}
}
return false;
}else{
guyTask.Remove(guyTaskArr[i]);
if (guyTask.Count == 0) return true;
guyTaskArr = guyTask.ToArray();
}
}
The PLINQ stuff looks "a bit" cleaner IMHO
The PLINQ approach would be this:
bool isBad = GetGuysToProcess().AsParallel().Any(g => g.TestForPossibleBadness());
Keep GetGuysToProcess as a sequence, run in parallel and find the first "bad" one.
精彩评论