我是否需要检查 Parallel.Foreach 中的 cancellationtoken
Do I need to check the cancellationtoken in Parallel.Foreach
这是 How to: Cancel a Parallel.For or ForEach Loop
的文档
我已经编写了一个使用该功能的方法:
static async Task SpreadCheer(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var friends = await GetFriends();
Parallel.ForEach(friends,
new ParallelOptions
{ CancellationToken = cancellationToken},
friend=>
{
SendCake(friend);
// (*1)
});
}
在文档中的示例中,在每个循环的最后一行,(*1)
。它添加了一个 cancellationToken.ThrowIfCancellationRequested
.
这让我很困惑,因为那我为什么要把它传递给并行选项。我也可以 see that 如果令牌被取消,Parallel.Foreach 将在处理项目后抛出。如果令牌从一开始就被取消,它还会在开始任何循环之前立即抛出。这也是我对 运行 和测试这段代码的经验,不需要明确抛出取消。
我需要(甚至应该)在位置 (*1)
中放置一个 cancellationToken.ThrowIfCancellationRequested
吗?
当然文档有它的示例,但它没有明确提及它,如果有一个单元测试涵盖这个,它不是通过该测试所需的代码。据我所知。
额外上下文:
有关取消的一些上下文。取消的原因是我有一个用于 SpreadCheer 的 Azure WebJob,传播欢呼可能需要一段时间,如果 Azure 向我发送关闭信号,我想优雅地停止传播欢呼。我不想弄乱任何人的蛋糕。
你应该在操作本身中使用 token.ThrowIfCancellationRequested()
的原因是,并行操作将继续执行直到最后。
Parallel.ForEach
只检查操作开始和结束时的令牌,中间不检查。
因此,如果您有很多并行操作或长 运行 操作,您需要自己检查操作中的取消。
您可以使用以下代码段验证行为,有或没有 token.ThrowIfCancellationRequested()
internal class Program
{
private static void Main()
{
var source = new CancellationTokenSource();
var token = source.Token;
Task.Run(() =>
{
Parallel.ForEach(Enumerable.Range(1, 100), new ParallelOptions {CancellationToken = token},
i =>
{
for (var y = 0; y < 100; y++)
{
token.ThrowIfCancellationRequested();
Thread.Sleep(1000);
Console.WriteLine($"{i} {y}");
}
});
}, token);
Console.WriteLine("press return to cancel...");
Console.ReadLine();
source.Cancel();
Console.WriteLine("press return to exit...");
Console.ReadLine();
}
}
这是 How to: Cancel a Parallel.For or ForEach Loop
的文档我已经编写了一个使用该功能的方法:
static async Task SpreadCheer(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var friends = await GetFriends();
Parallel.ForEach(friends,
new ParallelOptions
{ CancellationToken = cancellationToken},
friend=>
{
SendCake(friend);
// (*1)
});
}
在文档中的示例中,在每个循环的最后一行,(*1)
。它添加了一个 cancellationToken.ThrowIfCancellationRequested
.
这让我很困惑,因为那我为什么要把它传递给并行选项。我也可以 see that 如果令牌被取消,Parallel.Foreach 将在处理项目后抛出。如果令牌从一开始就被取消,它还会在开始任何循环之前立即抛出。这也是我对 运行 和测试这段代码的经验,不需要明确抛出取消。
我需要(甚至应该)在位置 (*1)
中放置一个 cancellationToken.ThrowIfCancellationRequested
吗?
当然文档有它的示例,但它没有明确提及它,如果有一个单元测试涵盖这个,它不是通过该测试所需的代码。据我所知。
额外上下文:
有关取消的一些上下文。取消的原因是我有一个用于 SpreadCheer 的 Azure WebJob,传播欢呼可能需要一段时间,如果 Azure 向我发送关闭信号,我想优雅地停止传播欢呼。我不想弄乱任何人的蛋糕。
你应该在操作本身中使用 token.ThrowIfCancellationRequested()
的原因是,并行操作将继续执行直到最后。
Parallel.ForEach
只检查操作开始和结束时的令牌,中间不检查。
因此,如果您有很多并行操作或长 运行 操作,您需要自己检查操作中的取消。
您可以使用以下代码段验证行为,有或没有 token.ThrowIfCancellationRequested()
internal class Program
{
private static void Main()
{
var source = new CancellationTokenSource();
var token = source.Token;
Task.Run(() =>
{
Parallel.ForEach(Enumerable.Range(1, 100), new ParallelOptions {CancellationToken = token},
i =>
{
for (var y = 0; y < 100; y++)
{
token.ThrowIfCancellationRequested();
Thread.Sleep(1000);
Console.WriteLine($"{i} {y}");
}
});
}, token);
Console.WriteLine("press return to cancel...");
Console.ReadLine();
source.Cancel();
Console.WriteLine("press return to exit...");
Console.ReadLine();
}
}