如何立即终止 Parallel.ForEach 线程

本文关键字:ForEach 线程 Parallel 终止 何立即 | 更新日期: 2023-09-27 18:31:24

我正在Parallel.Foreach()调用一些代码。代码有Thread.Sleep(60000),所以如果我也取消令牌,那么它会等待 60 秒,然后再取消 Parallel.ForEach 循环。 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();
        }
    }

如何立即终止 Parallel.ForEach 线程

如果我理解正确,并不是您需要立即中断线程,而是您只是希望在等待时能够中断Sleep()方法。

有许多选项,但恕我直言,最简单的选项之一是使用 CancellationToken.WaitHandle 属性值,然后等待该值而不是睡眠:

po.CancellationToken.WaitHandle.WaitOne(60000);

如果令牌发出信号,则 Wait() 方法将在指定的超时(在本例中为一分钟)之前返回。

通常你会检查返回值,这样你就可以分辨出发出信号的句柄和等待超时之间的区别,但在你的情况下,你会立即调用po.CancellationToken.ThrowIfCancellationRequested();,所以在我看来,忽略Wait()方法的返回值并让下一个程序语句负责实际中断方法似乎是合理的。