问题
I'm trying to implement a nested task inside a loop - this is the pattern I have so far, however I'm far from sure as this is the first time I've used the parallel task library.
The parent (tier) task should wait for the children (node) tasks to complete.
public int NestedTask(IEnumerable<MatchTier> tierNodes)
{
var tier = Task<int>.Factory.StartNew(() =>
{
Task<int> node = null;
foreach(var n in tierNodes)
{
node = Task<int>.Factory.StartNew(() =>
{
// Task logic goes here
return 1; // temp placeholder
});
// if a valid value is returned then exit this loop
}
return node.Result;
});
return tier.Result;
}
The child nodes loop until the first valid value is returned, then the loop should be exited, passing the valid value to the parent.
Both the child and parent nodes require a timeout too. Each child will be allowed approx 3 seconds to run after which the process will be timed out and the next node interrogated.
the parent has an overall timeout value of approx 15 - 20 seconds, after which, if no valid response has been recieved, it too should terminate.
Does this seem logical?
回答1:
As stated task.Wait(), task.Result (wait and grab result) and Task.WaitAll(theTaskCollection) are the ways to do this. I've changed your implementation slightly to account for that but I'm very unsure of what you really want to return. The outer task I removed since it didn't seem to be needed.
public int NestedTask(IEnumerable<MatchTier> tierNodes)
{
var tasks = tierNodes.Select(node => Task<int>.Factory.StartNew(() =>
{
// Task logic goes here
return 1; // temp placeholder
})).ToList(); // Enumerate to start tasks, not doing this would case WaitAll to start them one at a time (i believe)
if (!Task.WaitAll(tasks, timeOutInMilliseconds))
// Handle timeout...
return tasks.First().Result; // Is this what you want?
}
EDIT: Adding modified solution.
public int NestedTask(IEnumerable<string> tierNodes)
{
int parentTimeout = 15 * 1000;
int childTimeout = 3 * 1000;
var tier = Task<int>.Factory.StartNew(() =>
{
foreach (var n in tierNodes)
{
var node = Task<int>.Factory.StartNew(() =>
{
// Task logic goes here
return 1;
});
// If we get the result we return it, else we wait
if (node.Wait(childTimeout))
return node.Result;
}
throw new Exception("did not get result!");
});
if (!tier.Wait(parentTimeout))
{
// The child will continue on running though.
throw new TimeoutException("parent timed out");
}
else if (tier.Exception != null)
{
// We have an error
throw tier.Exception.InnerException;
}
return tier.Result;
}
回答2:
to wait for a task to complete do
node.Wait();
to wait for task up until some ticks do
node.Wait(timeToWait);
or to wait for them all to complete
Task.WaitAll(tasks);
and you should read here for more information
来源:https://stackoverflow.com/questions/18460464/nested-task-inside-loop