取消数据流 ActionBlock 中的特定任务
Cancelling specific task in a dataflow ActionBlock
经过一整天的搜索后,我发现了一条评论,即 TPL 数据流取消是一种开箱即用的方式,可以取消整个块,而不是单个 task/item。我的主要障碍是,如果我的操作块同时并行 运行 10 个任务,我该如何取消任务 #5?那里有很多取消示例,但它们都只使用一个取消令牌,并最终取消任务 #5 和它之后的所有任务。
这是一些非常精简的代码。我猜我必须与 "i" 一起传递一些东西,但不清楚如何以编程方式创建唯一的取消标记,再加上在这个特定示例中我可能需要 1 到 10 个取消标记。即使我在鼠标单击方法中创建了一个取消令牌,我是否必须根据现有令牌检查它以确保它是唯一的?好迷茫。
// 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);
}
如果您希望能够阻止它们,您需要一个取消令牌源列表,以便您可以分别向它们发送信号。如果你想要 work
中的每个元素一个,你可以 select 覆盖它:
var sources = work.Select( w => new CancellationTokenSource()).ToList();
然后,您必须修改DoStuff
以检查令牌:
void DoStuff(int i, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Do the rest of the stuff
}
}
而且调用的时候需要传递:
ActionBlock<int> throttle = new ActionBlock<int>(
action: i=>DoStuff(i, sources[i].Token), //<--- modified
dataflowBlockOptions: new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 10,
CancellationToken = cts.Token
});
然后要取消单个任务,请调用:
sources[i].Cancel();
经过一整天的搜索后,我发现了一条评论,即 TPL 数据流取消是一种开箱即用的方式,可以取消整个块,而不是单个 task/item。我的主要障碍是,如果我的操作块同时并行 运行 10 个任务,我该如何取消任务 #5?那里有很多取消示例,但它们都只使用一个取消令牌,并最终取消任务 #5 和它之后的所有任务。
这是一些非常精简的代码。我猜我必须与 "i" 一起传递一些东西,但不清楚如何以编程方式创建唯一的取消标记,再加上在这个特定示例中我可能需要 1 到 10 个取消标记。即使我在鼠标单击方法中创建了一个取消令牌,我是否必须根据现有令牌检查它以确保它是唯一的?好迷茫。
// 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);
}
如果您希望能够阻止它们,您需要一个取消令牌源列表,以便您可以分别向它们发送信号。如果你想要 work
中的每个元素一个,你可以 select 覆盖它:
var sources = work.Select( w => new CancellationTokenSource()).ToList();
然后,您必须修改DoStuff
以检查令牌:
void DoStuff(int i, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Do the rest of the stuff
}
}
而且调用的时候需要传递:
ActionBlock<int> throttle = new ActionBlock<int>(
action: i=>DoStuff(i, sources[i].Token), //<--- modified
dataflowBlockOptions: new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 10,
CancellationToken = cts.Token
});
然后要取消单个任务,请调用:
sources[i].Cancel();