[英]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.