2011-08-02 126 views
7

我要找調用多個異步操作與能力取消它們的簡單方法:如何等待多個異步操作完成

var cancelTask = new ManualResetEvent(false); 
IAsyncResult ar = StartAsyncBatch(cancelTask); 
int resp = WaitHandler.WaitAny({ar.AsyncWaitHandle, cancelTask}); 

我如何要建立StartAsyncBatch?它應該被派生類

class StartAsyncBatch : IAsyncResult 

回答

8

簡要的回答是,你可以通過相應的CancellationTokenSource內置的CancellationToken取消等待任務。這是一個例子。

var tokenSource = new CancellationTokenSource(); 

var task = Task.Factory.StartNew(() => 
{ 
    for (int i = 0; i < 10; i++) 
    { 
     if (tokenSource.IsCancellationRequested) 
     { 
      //you know the task is cancelled 
      //do something to stop the task 
      //or you can use tokenSource.Token.ThrowIfCancellationRequested() 
      //to control the flow     
     } 
     else 
     { 
      //working on step i 
     } 
    } 
}, tokenSource.Token); 

try 
{ 
    task.Wait(tokenSource.Token); 
} 
catch (OperationCanceledException cancelEx) 
{ 
    //roll back or something 
} 

//somewhere e.g. a cancel button click event you call tokenSource.Cancel() 

當您處理幾項任務時,情況會有所不同。首先你需要知道什麼時候取消任務,其他任務會繼續嗎?如果是,您需要爲不同的任務創建不同的取消令牌並獨立處理取消。否則,他們可以共享相同的取消令牌。不同的要求導致不同的取消處理策略

2

如果您使用.NET 3.5或4.0,我會推薦使用任務並行庫(TPL)。控制任務要容易得多,而且您在控制/取消任務方面擁有更多的靈活性。檢查鏈接Task Parallelism如果您使用TPL並且您需要取消所有或任何您需要創建CancellationToken的任務以下是如何執行此操作的示例Task Cancellation

是的,你可以在.NET 3.5中使用TPL。這裏是鏈接怎麼做Reactive Extensions and Parallel Extensions基本上你需要安裝反應性擴展(Rx)

0

Danny的代碼在邏輯上是正確的,但實際上不運行。當WaitHandle.WaitAll()被調用時,程序被阻塞(包括兩個任務)。可以創建一個新線程來等待所有事件發出信號:

Thread t = new Thread(() => 
{ 
     WaitHandle.WaitAll(handles); 
     MessageBox.Show("Both Threads are finished"); 
}); 
t.Start();