我在Parallel.Foreach()
中调用了一些代码。代码有Thread.Sleep(60000)
,所以如果我也取消了令牌,那么它会在取消Parallel.ForEach循环之前等待60秒。
Thread.Sleep()
放在此代码中以供解释。实际代码有一些代码等待其他资源。
我希望在调用cts.Cancel();
时取消所有活动。
我也尝试过LoopState,但在我的情况下它不起作用。
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] nums = Enumerable.Range(0, 10000000).ToArray();
CancellationTokenSource cts = new CancellationTokenSource();
// Use ParallelOptions instance to store the CancellationToken
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Console.WriteLine("Press any key to start. Press 'c' to cancel.");
Console.ReadKey();
// Run a task so that we can cancel from another thread.
Task.Factory.StartNew(() =>
{
if (Console.ReadKey().KeyChar == 'c')
{
cts.Cancel();
}
Console.WriteLine("press any key to exit");
});
try
{
Parallel.ForEach(nums, po, (num) =>
{
double d = Math.Sqrt(num);
Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000); //Thread Sleep for 1 minute
po.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (OperationCanceledException e)
{
Console.WriteLine(e.Message);
}
finally
{
cts.Dispose();
}
Console.ReadKey();
}
}
答案 0 :(得分:2)
如果我理解正确,那么你需要立即中断线程 ,而只是想让它在等待时能够中断Sleep()
方法。
有许多选项,但最简单的恕我直言之一是使用CancellationToken.WaitHandle
属性值,并等待而不是睡觉:
po.CancellationToken.WaitHandle.WaitOne(60000);
如果发出令牌信号,Wait()
方法将在指定超时之前返回(在这种情况下为一分钟)。
通常你会检查返回值,这样你就能分辨出被发信号的句柄和等待超时之间的区别,但在你的情况下你会立即调用po.CancellationToken.ThrowIfCancellationRequested();
,所以对我来说这似乎是合理的忽略Wait()
方法的返回值,让下一个程序语句负责实际中断方法。