2013-08-27 63 views
3

我想在循环内部实现一个嵌套的任务 - 这是我迄今为止的模式,但我很不确定,因为这是我第一次使用并行任务库。嵌套任务循环内

父级(层)任务应等待子节点(节点)任务完成。

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; 
    } 

子节点循环,直到返回第一个有效的值,则循环将被退出,传递有效值父。

子节点和父节点都需要超时。每个孩子将被允许运行约3秒钟,之后该过程将被超时并且下一个节点被询问。

父母的总体超时值约为15-20秒,在此之后,如果没有收到有效的回复,它也应该终止。

这是否合乎逻辑?

+0

老实说,你只是在等待最后的结果并返回。你真的想做什么? – flindeberg

+0

请问您可以添加更多的细节。 tierNodes是您父节点还是子节点的共享?你如何从父节点获取子节点。我无法在代码中看到任何父母子女关系。多一点信息会有帮助 – Anand

+0

@Anand - 增加更多细节。 – dotnetnoob

回答

1

如上所述task.Wait(),task.Result(等待和抓取结果)和Task.WaitAll(theTaskCollection)是如何做到这一点。我已经稍微改变了你的实现来解释这一点,但我很不确定你真的想要返回什么。我除去了外部任务,因为它似乎并不需要。

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? 
} 

编辑:添加修改后的解决方案。

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; 
} 
+0

外部任务将需要,因为下一个阶段将添加一些超时逻辑。但是为了清楚起见,我没有这么做。 – dotnetnoob

+0

@dotnetnoob为什么不在较低的任务级别有超时? – flindeberg

+0

不同的超时时间将适用于每个节点 - 节点将有3秒的超时时间,并且parernt层的超时时间为15-20秒。超时前允许每个节点运行指定的时间。下一个节点被测试,依此类推,直到返回calid值或所有节点耗尽。如果父级超时发生,整个过程将被放弃,并且下一级将被测试。 – dotnetnoob

3

等待任务完成不

node.Wait(); 

等待任务,直到一些蜱做

node.Wait(timeToWait); 

或等待他们全部完成

Task.WaitAll(tasks); 

并且您应该阅读here以获取更多信息

+0

我明白,使用parent.Result会强制父母等待。 – dotnetnoob

+0

@dotnetnoob你正在做node.Result只在最后一项... –