简体   繁体   English

在C#中完成任务后如何停止所有任务

[英]How to stop all tasks when one is finished in c#

I have different tasks to read from different files and find a word into them. 我有不同的任务要从不同的文件读取并在其中找到单词。 I have put them into a task array which I start with waitAny method as following : 我将它们放入一个以waitAny方法开始的任务数组中,如下所示:

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

I would like to stop all other tasks as soon as one of the tasks finishes (it finishes when it founds the word). 我想在其中一项任务完成后立即停止所有其他任务(找到单词后即完成)。 For the moment, with waitany, i can know when one tasks finishes, but I don't know how I could know which one has finished and how to stop other tasks. 目前,使用waitany,我可以知道一个任务何时完成,但是我不知道如何知道哪个任务已经完成以及如何停止其他任务。 What would be the best way to achieve this ? 实现此目标的最佳方法是什么?

You can use single CancellationToken which all tasks will share. 您可以使用所有任务将共享的单个CancellationToken Inside mySearch.Invoke method verify value of token.IsCancellationRequested to cancel task. 里面mySearch.Invoke方法验证的价值token.IsCancellationRequested取消任务。 When some task will be finished cancel others via CancellationTokenSource.Cancel() . 完成某些任务后,请通过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();

BTW you can force token to throw OperationCanceledException when source is canceled by calling token.ThrowIfCancellationRequested() 顺便说一句 ,当通过调用token.ThrowIfCancellationRequested()取消源时,您可以强制令牌抛出OperationCanceledException token.ThrowIfCancellationRequested()

When creating a Task you can pass a CancelationToken . 创建任务时,可以传递CancellationToken Set this token when one of the tasks finishes. 其中一项任务完成时,请设置此令牌。 This will cause remaining tasks with this token to not execute . 这将导致其余带有此令牌的任务无法执行 Running tasks can receive a OperationCanceledException and stop too. 运行中的任务可以接收OperationCanceledException并停止。

I highly suggest reading How do I cancel non-cancelable async operations? 我强烈建议您阅读如何取消不可取消的异步操作? by Stephen Toub. 由Stephen Toub。 Essentially what you need to do is cancel all of these tasks, but currently you have no mechanism to cancel them. 本质上,您需要做的是取消所有这些任务,但是目前您没有机制来取消它们。

The ideal approach would be to create a CancellationTokenSource before the foreach, pass the CancellationToken from that source to each of the child tasks, check that token periodically and stop doing work when you notice it's indicated cancellation. 理想的方法是在foreach之前创建一个CancellationTokenSource ,将CancellationToken从该源传递到每个子任务,定期检查该令牌,并在发现已指示取消时停止工作。 You can then cancel the token source in the WhenAny continuation. 然后,您可以在WhenAny延续中取消令牌源。

If that's not an option you need to decide if it's important to actually stop the tasks (which, really, just can't be done) or if you just need to continue on with your code without waiting for them to finish (that's easy enough to do). 如果这不是一个选择,则需要确定实际上停止任务是否很重要(这实际上是无法完成的),或者仅需继续执行代码而无需等待它们完成(这很容易)去做)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM