迭代parallel.foreach时,我可以只取消一个线程吗?

时间:2016-12-11 10:48:15

标签: .net multithreading parallel-processing parallel.foreach

当我使用parallel.foreach时,有没有办法取消一个特定的帖子?

我知道我可以使用cancelToken.token使用parallelOptions()取消所有主题,但如何取消一个特定主题

我知道如果我创建一个线程列表而不是parallel.foreach,那么选择要取消的线程没有问题,但我希望我的程序以并行顺序运行而不仅仅是异步(因为我想要使用我所有的CPU,而不仅仅是切断CPU资源。)

3 个答案:

答案 0 :(得分:3)

编辑:好的,所以我的第一个想法很糟糕,但这很有效:

List<string> Items = new List<string>()
{
    "First",
    "Second",
    "Third",
    "Fourth"
};

Parallel.ForEach(Items, (s, t) =>
{
    if (s == "Second")
        return;
    Console.WriteLine(s);
});

我想这将教会我在不等待Visual Studio的情况下发布答案,从中吸取教训:P

答案 1 :(得分:2)

正如William Xifaras已经提到过,如果您使用Parallel.ForeachParallel.For,那么ThreadPool将用于执行您的代码。

为什么不使用Task<T>来编写类似的功能,但请记住这样的取消。

        Action<CancellationToken> work = (token) =>
        {
            Console.WriteLine($"Work started on Thread: {Thread.CurrentThread.ManagedThreadId}");
            foreach (var i in Enumerable.Range(0, 10))
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine($"Work cancelled on Thread: {Thread.CurrentThread.ManagedThreadId}");
                    return;
                }
                Thread.Sleep(1000);
            }
            Console.WriteLine($"Work complete on Thread: {Thread.CurrentThread.ManagedThreadId}");
        };

        var tasks = new List<Tuple<Task, CancellationTokenSource>>();

        foreach (var i in Enumerable.Range(0, 4))
        {
            var cancellation = new CancellationTokenSource();
            var task = Task.Run(() => work(cancellation.Token), cancellation.Token);
            tasks.Add(new Tuple<Task, CancellationTokenSource>(task, cancellation));
        }

        tasks.First().Item2.Cancel();
        Task.WaitAll(tasks.Select(m => m.Item1).ToArray());

这将产生类似的输出:

Work started on Thread: 3
Work started on Thread: 6
Work started on Thread: 4
Work started on Thread: 5
Work cancelled on Thread: 3
Work complete on Thread: 6
Work complete on Thread: 5
Work complete on Thread: 4

这是你试图实现的目标吗?

答案 2 :(得分:1)

为了清楚起见,Parallel类使用ThreadPool来排队并执行工作。

要回答您的问题,我认为您无法取消特定的“线程”本身,但是您可以在不使用取消令牌的情况下从Parallel.For中断。

请参阅MSDN上的以下内容:如何:Stop or Break from a Parallel.For Loop