如何等待多个异步操作完成

7
我正在寻找一种简单的方法来调用多个异步操作,并具有取消它们的能力:
var cancelTask = new ManualResetEvent(false);
IAsyncResult ar = StartAsyncBatch(cancelTask);
int resp = WaitHandler.WaitAny({ar.AsyncWaitHandle, cancelTask});

我该如何构建StartAsyncBatch?它应该派生自哪个类呢?
class StartAsyncBatch : IAsyncResult
3个回答

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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接