2012-08-14 2 views
6

여러 작업이 완료 될 때까지 Task.WhenAll을 사용하려고합니다.Task.WhenAll()을 올바르게 사용하는 방법

내 코드는 다음과 같습니다. 여러 개의 비동기 작업을 시작해야하는데, 각각의 비동기 작업은 버스 경로를 검색 한 다음 로컬 배열에 추가합니다. 그러나 Task.WhenAll (...)은 즉시 반환하고 로컬 경로 배열의 개수는 0입니다. 이것은 각 작업 내에서 다양한 '대기 중'문이 흐름이 일시 중단되고 작업이 완료 될 때까지 반환되지 않는다는 것을 의미하기 때문에 이상하게 보입니다.

 List<Task> monitoredTasks = new List<Task>(); 
     foreach (BusRouteIdentifier bri in stop.services) 
     { 
      BusRouteRequest req = new BusRouteRequest(bri.id); 

      // Start a new task to fetch the route for each stop 
      Task getRouteTask = Task.Factory.StartNew(async() => 
      { 
       var route = await BusDataProviderManager.DataProvider.DataBroker.getRoute(req); 

        // Add the route to our array (on UI thread as it's observed) 
        await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate 
        { 
         this.routes.Add(route); 
        }); 
      }); 

      // Store the task in our monitoring list 
      monitoredTasks .Add(getRouteTask); 
     } 

     Debug.WriteLine("Awaiting WHENALL"); 
     await Task.WhenAll(monitoredTasks); 
     Debug.WriteLine(string.Format("WHENALL returned (routes count is {0} ", this.routes.Count)); 

     this.OnWillEndFetchingRoutes(new EventArgs()); 

분명히 뭔가 잘못하고 있습니다.하지만 뭐라 구요?

+0

당신이 마지막은'Task'가 오류 상태에 있지 여부를 확인하기 위해 시도에

 List<Task<BusRoute>> routeRetrievalTasks = new List<Task<BusRoute>>(); foreach (BusRouteIdentifier bri in stop.services) { BusRouteRequest req = new BusRouteRequest(bri.id); routeRetrievalTasks.Add(BusDataProviderManager.DataProvider.DataBroker.getRoute(req)); } foreach (var task in routeRetrievalTasks) { var route = await task; this.routes.Add(route); // triggers events } 

감사 :

내가 원하는 것을 달성하기 위해, 나는 다음과 같이 리팩토링하는 데 필요한? –

+0

foreach 루프 내에서 'dispatcher'가 잘못 될 수 있습니다. UI 스레드가 관찰되고 즉시 표시됩니까? –

+0

@ie. 예, 상태는 RanToCompletion입니다. 배열의 모든 작업 상태는 RanToCompletion도 있지만 실제로 개별적으로 검사 할 때 각 결과 필드는 WaitingForActivation입니다. –

답변

6

이 어떻게 진짜로 작동 비동기 기다리고의 이해의 기초 부족으로 내려했다.

내부 작업이 외부 작업으로 흐름을 되돌려 놓았습니다. 외부 작업은 대기 상태가되기 전에 완료되었습니다. Dave Smits

5

문제가 Task.Factory.StartNew() 전화 인 것 같습니다. 나는 당신이 Task<Task>으로 끝나는 것 같아요. 실제로는 작업을 시작할 때만 알면됩니다.

대신을 시도해보십시오

Func<Task> taskFunc = async() => 
{ 
    var route = await BusDataProviderManager.DataProvider.DataBroker.getRoute(req); 

    // Add the route to our array (on UI thread as it's observed) 
    await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate 
    { 
     this.routes.Add(route); 
    }); 

} 

Task getRouteTask = Task.Run(taskFunc); 
+0

감사합니다. 나머지 메서드는 이전과 같이 계속 수행됩니다. 즉, 작업 배열에 작업을 추가 한 다음 배열의 Task.WhenAll (...)을 호출합니다. 그렇다면이 접근법과 내 답변의 비교 방법은 어떤 관계가 있습니까? 이점이 있습니까? –

+0

@CarlosP : 솔직하게 말하면 나는 더 나은 접근법에 대해 논평하기에 충분한 문맥을 가지고 있지 않습니다. 하지만 예, 나머지 방법은 이전과 같이 계속됩니다. –

관련 문제