2011-08-10 54 views
5

我正在将线程安装到我的Azure代码中,以便将队列放入队列中。为此,我使用http://www.microsoft.com/download/en/details.aspx?id=19222作为参考。Task.Wait在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); 
    } 
} 

现在的问题是关于在Task.Wait延续(这是根据由MS提供的文件)。等待你已经知道已经完成的线程似乎有点奇怪?我能想象的唯一原因就是冒泡和处理这些错误。我在这里错过了什么?

回答

4

Task.WaitAll()将在至少有一个Task实例被取消时抛出AggregateException - 或者 - 至少执行一个Task实例期间抛出异常。

ContinueWhenAll()不会抛出此异常及其只需启动你的最后一个任务,当一切都结束取消与否等

+0

我想我们同意我的假设呢? –

+0

@迪迪耶是的 - 忘记那部分在我的回答:) – Skomski

2

首先,我注意到您使用的是List<T>Parallel.ForEach这是不是线程安全的,应更换它与同时收集,例如:ConcurrentQueue<T>

关于WaitAll VS ContinueWhenAll,如果任何任务出现故障WaitAll将抛出,所以上面的代码是验证所有任务都成功完成,如果你通过ContinuationOptions参数ContinueWhenAllOnlyRanToCompeletion所以你可以做同样的只有在所有任务都成功完成后,才会安排延续任务。

+0

嗨!感谢有关线程安全的指针..明确救生员。 –