2014-10-30 7 views
1

I가 다음 노드 :확인을 IEnumerable 방법 비동기

class Node 
{ 
    public string Name;   
    public IEnumerable<Node> Children; 
} 

나는 다음과 같은 확장 방법이 있습니다

public static class ExtensionMethods 
{ 
    public static IEnumerable<Node> TraverseTree(this Node root) 
    { 
     if (root.Children != null) 
     { 
      foreach (var child in root.Children) 
      { 
       var nodes = TraverseTree(child); 
       foreach (var node in nodes) 
       { 
        yield return node; 
       } 
      } 
     } 

     yield return root; 
    }  
} 

나는 이름이 "푸"와 트리에서 노드를 검색 할을 . 이를 위해 내가 할 :

Node myNode = /* some large tree! */ 
var search = myNode.TraverseTree().Where(x=>x.Name == "Foo").FirstOrDefault(); 

나는 3 개 목표

  1. 이 방법을 가지고 TraverseTree 수율 (IEnumerable을)와 트리 트래버스 그래서 제 3 회 노드 이름이 발생할 경우 그 = = "Foo"그러면 전체 트리를 가로 지르지 않아도됩니다. 지금이 경우는입니다.
  2. 찾을 때까지 시간이 오래 걸릴 수 있으므로 TraverseTree 메서드를 별도의 스레드에서 실행하십시오. 따라서 TraverseTree 메서드는 callBack 매개 변수를 사용해야한다고 생각하십니까?
  3. 마지막으로 해당 작업을 취소 할 수 있으면 좋을 것입니다. 해당 메서드에 취소 토큰도 전달해야합니까?

올바른 방법은 무엇입니까?

죄송합니다 제가 닷넷 프레임 워크 4.0

+0

도와 줘? http://stackoverflow.com/a/20281941/1210520 –

+0

가능한 중복 [Task.WhenAny 할 때 반환 항목을 양보하는 방법] (http://stackoverflow.com/questions/18284169/how-to-yield-return- item-when-doing-task-whenany) –

답변

1
  1. 이 이미 당신이 가지고있는 코드로 이루어집니다를 사용하고 언급하는 것을 잊었다. 예. 지연 실행.
  2. 이렇게하는 것이 훨씬 쉬운 방법은 메서드를 동기식으로 유지하고 전체 쿼리를 다른 스레드로 옮기는 것입니다.
  3. 예, 통과 알고리즘, 자식 선택기 또는 둘 모두에 의해 검사되는 CancellationToken은 확실히 추가 할 수있는 항목입니다. 다른 옵션은 계산을 실제로 멈추려 고 시도하는 대신 탐색 중지 대기의 결과를 기다리는 것이 무엇이든간에 기다리는 것입니다. 나중에 그런

    var cts = new CancellationTokenSource(); 
    
    var task = Task.Run(
        () => myNode.TraverseTree(cts.Token).Where(x=>x.Name == "Foo").FirstOrDefault(), 
        cts.Token); 
    

    : 그럼

    public static IEnumerable<Node> TraverseTree(this Node root, CancellationToken token) 
    { 
        if (root.Children != null) 
        { 
         foreach (var child in root.Children) 
         { 
          if (token.IsCancellationRequested) return; //cancel if requested. 
    
          var nodes = TraverseTree(child); 
          foreach (var node in nodes) 
          { 
           yield return node; 
           if (token.IsCancellationRequested) return; //cancel if requested. 
          } 
         } 
        } 
    
        yield return root; 
    }  
    

    (CancellationToken의 사용을주의)처럼

0

첫째, 당신의 기능을 구현하는 것, 여기에 호출은 다음과 같은 형태가 될 것이다 을 (를) 취소하려면 다음 번호로 전화하십시오.

cts.Cancel(); 
+0

나는 누가 투표를했는지 알지 못하지만 이유를 알면 좋을 것이다. 나는 그것을 곧 시도 할 것이다. –