简体   繁体   English

取消数据流 ActionBlock 中的特定任务

[英]Cancelling specific task in a dataflow ActionBlock

After spending all day searching I came across a comment that TPL Dataflow cancellation comes out of the box as a way to cancel an entire block, and not an individual task/item.在花了一整天的时间搜索后,我发现一条评论说 TPL 数据流取消开箱即用,是取消整个块而不是单个任务/项目的一种方式。 My main stumbling block is how do I go about cancelling Task #5 if my Action block is concurrently running 10 tasks in parallel?我的主要绊脚石是如果我的 Action 块同时并行运行 10 个任务,我该如何取消任务 #5? There are quite a few cancellation examples out there, but they all use just one cancellation token, and end up cancelling Task #5 and all the tasks after it.那里有很多取消示例,但它们都只使用一个取消令牌,并最终取消了任务 #5 及其之后的所有任务。

Here is some very stripped down code.这是一些非常精简的代码。 I am guessing I have to pass something along with "i", but unclear how to programatically create unique cancellation tokens, coupled with the fact I may need anywhere from 1 to 10 of them in this particular example.我猜我必须与“i”一起传递一些东西,但不清楚如何以编程方式创建唯一的取消令牌,再加上在这个特定示例中我可能需要 1 到 10 个。 Even if I create a cancellation token in the mouse-click method, do I then have to check it against existing tokens to make sure it is unique?即使我在鼠标单击方法中创建了一个取消令牌,我是否还必须根据现有令牌检查它以确保它是唯一的? So confused.如此迷茫。

            // Define the action block
        ActionBlock<int> throttle = new ActionBlock<int>(
            action: i=>DoStuff(i),
            dataflowBlockOptions: new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = 10,
                CancellationToken = cts.Token
            });

        // Create the work set (pretend it is a mouse-click method... it will not be a for loop)
        for (int i = 0; i < work.Length; i++)
        {
            Console.WriteLine($"{i:D3} : Posting Work Item {i}.");
            throttle.Post(i);
        }

If you want to be able to stop them, you need a list of cancellation token sources so that you can signal them individually.如果您希望能够阻止它们,您需要一个取消令牌源列表,以便您可以单独向它们发出信号。 If you want one per element in work you could just select over it:如果您希望work每个元素都有一个,您可以选择它:

var sources = work.Select( w => new CancellationTokenSource()).ToList();

Then, you have to modify DoStuff to check the token:然后,您必须修改DoStuff以检查令牌:

void DoStuff(int i, CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        //Do the rest of the stuff
    }
}

And you need to pass it when you call it:并且在调用时需要传递它:

ActionBlock<int> throttle = new ActionBlock<int>(
    action: i=>DoStuff(i, sources[i].Token),  //<--- modified
    dataflowBlockOptions: new ExecutionDataflowBlockOptions
    {
        MaxDegreeOfParallelism = 10,
        CancellationToken = cts.Token
    });

Then to cancel an individual task, call:然后要取消单个任务,请调用:

sources[i].Cancel();

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

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