2

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?

4
  • In all honesty you are only waiting for the last result and returning that. What are you really trying to do? Commented Aug 27, 2013 at 8:26
  • Could you please add more details. tierNodes is collecion of your parent node or child node ? How you are getting child nodes from parent nodes. I am not able to see any parent child relationship in th code. A little more info would be helpful Commented Aug 27, 2013 at 8:26
  • @Anand - added more details. Commented Aug 27, 2013 at 9:21
  • Why do you use a task tier if you wait for its result at the end of the method? Or: why don't you just use the inner loop creating Tasks? Commented Aug 27, 2013 at 9:32

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

1 Comment

I understood that using parent.Result would force the parent to wait.
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;
}

6 Comments

The outer task will be needed as the next stage will be to add some timeout logic. However I refrained from doing so for clarity.
@dotnetnoob Why not have the timeout on the lower task level instead?
Different timeouts will apply to each - a node will have a timeout of 3 seconds and the parernt tier will have a timeout of 15-20 seconds. Each nodes is allowed to run for a specified time before being timed out. The next node is tested and so on until a calid value is returned or all nodes are exhausted. If the timeout on the parent occurs the whole process is abandoned and the next tier will be tested.
@dotnetnoob I added a new solution for your new requirements. Hopefully it helps u!
Thanks - i'll set up some tests and try it out.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.