2011-08-10 9 views
5

대기열에 물건을 넣기 위해 푸른 색 코드에 스레드를 실어 가려고했습니다. 이렇게하려면 http://www.microsoft.com/download/en/details.aspx?id=19222을 참조로 사용했습니다. 여러 메시지를 대기열하기Task.Wait in ContinueWhenAll Action

내 코드는 다음과 같습니다

public void AddMessagesAsync(IEnumerable<IQueueMessage> messages, string queue = null, TimeSpan? timeToLive = null) 
{ 
    //check if we need to switch queues 
    if (!String.IsNullOrEmpty(queue)) 
    { 
    SetCurrent(queue); 
    } 

    //setup list of messages to enqueue 
    var tasks = new List<Task>(); 
    Parallel.ForEach(messages, current => { 
    if (timeToLive.HasValue) 
    { 
     //create task with TPL 
     var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), timeToLive.Value, tasks); 
     //setup continuation to trigger eventhandler 
     tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t))); 
    } 
    else 
    { 
     //create task with TPL 
     var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), tasks); 
     //setup continuation to trigger eventhandler 
     tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t))); 
    } 
    }); 

    //setup handler to trigger when all messages are enqueued, a we are blocking the thread over there to wait for all the threads to complete 
    Task.Factory.ContinueWhenAll(tasks.ToArray(), (t) => AddMessagesCompleted(t));    
} 

private void AddMessagesCompleted(Task[] tasks) 
{ 
    try 
    { 
    //wait for all tasks to complete 
    Task.WaitAll(tasks); 
    } 
    catch (AggregateException e) 
    { 
    //log the exception 
    var ex = e; 
    //return ex; 
    } 

    if (AddedMessages != null) 
    { 
    AddedMessages(tasks, EventArgs.Empty); 
    } 
} 

지금 내 질문 (MS에서 제공하는 문서에 따라 됨) 연속의 Task.Wait에 관한 것입니다. 이미 올바르게 완료되었다는 것을 이미 알고있는 스레드를 기다리는 것이 약간 이상하게 보입니까? 제가 상상할 수있는 유일한 이유는 오류를 버블 링하고 처리하는 것입니다. 내가 여기서 뭔가를 놓치고 있니?

답변

4

Task.WaitAll()은 적어도 하나의 작업 인스턴스가 취소 될 때 AggregateException을 던집니다. 또는 하나 이상의 작업 인스턴스를 실행하는 동안 예외가 발생했습니다.

ContinueWhenAll()이 예외를 발생하고 단순히

+0

우리는 내 가정에 동의 할 것 같습니까? –

+0

@Didier 예 - 내 대답에 그 부분을 잊지 :) – Skomski

2

먼저 등 모든 마감이 취소 될 때 마지막 작업을 시작하거나하지 않을 것이다, 당신이 스레드 안전하지 않은 Parallel.ForEachList<T>을 사용 나타났습니다, 당신은 교체해야 동시 수집이있는 예 : ConcurrentQueue<T>. WaitAllContinueWhenAll에 관한

, 작업 중 오류가 발생한 경우 위의 코드는 모든 작업이 성공적으로 완료 확인하는 것입니다, 그래서 WaitAll 당신이 그렇게 OnlyRanToCompeletion처럼 ContinueWhenAllContinuationOptions 매개 변수를 전달하면 같은 작업을 수행 할 수 있습니다, 슬로우합니다 모든 작업이 성공적으로 완료된 경우에만 계속 작업이 예약됩니다.

+0

안녕하세요! 스레드 안전에 대한 포인터 주셔서 감사합니다 .. 확실한 생명의 은인. –