如果条件满足,不立即取消所有线程
本文关键字:取消 线程 条件 满足 如果 | 更新日期: 2023-09-27 18:11:57
代码总是等待当前运行的任务完成后才抛出OperationCancelledException
。
我希望程序在条件为真时立即停止。
static void Main()
{
// want to break out of a Parallel.For immediately when a condition occurs
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
po.CancellationToken = cts.Token;
long counterTotal = 0;
try
{
// want to have a sum of counts at the end
Parallel.For<long>(1, 26, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
{
po.CancellationToken.ThrowIfCancellationRequested();
Console.WriteLine(i.ToString());
for (int k = 0; k < 1000000000; k++)
{
counterSubtotal++;
if (i == 4 && k == 900000000)
{
cts.Cancel();
// Would like to break out here immediately
}
}
return counterSubtotal;
}, (x) => Interlocked.Add(ref counterTotal, x)
);
}
catch (OperationCanceledException e)
{
Console.WriteLine("Cancelled");
Console.WriteLine("Total iterations across all threads {0}", String.Format("{0:n0}", counterTotal));
Console.ReadLine();
}
}
我发现在cts.Cancel()
和catch中放置一个断点可以演示正在发生的事情。
我也看过state.Stop
。
这是其他代码的简化版本。
如果我们想要立即爆发,可能Parallel.For
对于在方法内运行很长时间的事情不是理想的。
更新2:代码现在按预期工作,并给出了一个很好的总数
static void Main()
{
// want to break out of a Parallel.For immediately when a condition occurs
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
po.CancellationToken = cts.Token;
long counterTotal = 0;
try
{
// want to have a sum of counts at the end
// using type param here to make counterSubtotal a long
Parallel.For<long>(1, 26, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
{
Console.WriteLine(i.ToString());
// 1 billion
for (int k = 0; k < 1000000000; k++)
{
//po.CancellationToken.ThrowIfCancellationRequested();
if (po.CancellationToken.IsCancellationRequested)
{
return counterSubtotal;
}
counterSubtotal++;
if (i == 4 && k == 400000000)
{
Console.WriteLine("Inner Cancelled");
cts.Cancel();
}
}
return counterSubtotal;
}, (x) => Interlocked.Add(ref counterTotal, x)
);
}
catch (OperationCanceledException e)
{
Console.WriteLine("Cancelled");
Console.WriteLine("Total iterations across all threads {0}", String.Format("{0:n0}", counterTotal));
Console.ReadLine();
}
}
如果您希望它"立即"中断,那么您需要检查inner for中的取消令牌。就像现在一样,它将在输入之前检查是否取消,但在此之后它将不再查看令牌。
for (int k = 0; k < 1000000000; k++)
{
po.CancellationToken.ThrowIfCancellationRequested();
counterSubtotal++;
if (i == 4 && k == 900000000)
{
cts.Cancel();
}
}