5

我有不同的任务要从不同的文件中读取并在其中找到一个单词。我已将它们放入一个任务数组中,我以 waitAny 方法开始,如下所示:

foreach (string file in filesList)
        {
            files[i] = Task.Factory.StartNew(() =>
            {
                mySearch.Invoke(file);
            });
            i++;
        }
        System.Threading.Tasks.Task.WaitAny(files);

我想在其中一项任务完成后立即停止所有其他任务(它在找到单词时完成)。目前,使用waitany,我可以知道一项任务何时完成,但我不知道如何知道哪一项已完成以及如何停止其他任务。实现这一目标的最佳方法是什么?

4

3 回答 3

2

您可以使用CancellationToken所有任务将共享的单个。内部mySearch.Invoke方法验证token.IsCancellationRequested取消任务的值。当某些任务完成时,通过取消其他任务CancellationTokenSource.Cancel()

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token; 

foreach (string file in filesList)
{
   // pass cancellation token to your task
   files[i] = Task.Factory.StartNew(() => mySearch.Invoke(file, token), token);
   i++;
}

Task.WaitAny(files);
tokenSource.Cancel();

顺便说一句OperationCanceledException,您可以通过调用取消源时强制抛出令牌token.ThrowIfCancellationRequested()

于 2012-11-29T16:07:54.943 回答
2

创建任务时,您可以传递CancelationToken。当其中一项任务完成时设置此令牌。这将导致具有此令牌的剩余任务无法执行。正在运行的任务也可以接收OperationCanceledException并停止。

于 2012-11-29T16:08:17.277 回答
1

我强烈建议阅读如何取消不可取消的异步操作?斯蒂芬·图布。本质上,您需要做的是取消所有这些任务,但目前您没有取消它们的机制。

理想的方法是CancellationTokenSource在 foreach 之前创建一个,将CancellationToken来自该源的 传递给每个子任务,定期检查该令牌并在您注意到它被指示取消时停止工作。然后,您可以继续取消令牌源WhenAny

如果这不是一个选项,您需要决定是否真正停止任务很重要(这实际上是无法完成的),或者您是否只需要继续编写代码而不等待它们完成(这很容易去做)。

于 2012-11-29T16:09:49.443 回答