使用 Task.WaitAll(线程)不会适当地阻塞

本文关键字:WaitAll Task 线程 使用 | 更新日期: 2023-09-27 18:34:05

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Threads
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<int> TestingDelegate = (x321) => { Console.WriteLine(x321); };
            int x123 = Environment.ProcessorCount;
            MyParallelFor(0, 8, TestingDelegate);
            Console.Read();
        }
        public static void MyParallelFor(int inclusiveLowerBound, int exclusiveUpperBound, Action<int> body)
        {
            int size = exclusiveUpperBound - inclusiveLowerBound;
            int numProcs = Environment.ProcessorCount;
            int range = size / numProcs;
            var threads = new List<Task>(numProcs);
            for(int p = 0; p < numProcs; p++)
            {
                int start = p * range + inclusiveLowerBound;
                int end = (p == numProcs - 1) ? exclusiveUpperBound : start + range;
                Task.Factory.StartNew(() =>
                {
                    for (int i = start; i < end; i++) body(i);
                });
            }
            Task.WaitAll(threads.ToArray());
            Console.WriteLine("Done!");
        }
    }
}

大家好,我实现了并行编程模式一书中的这段代码,他们使用线程来完成,我决定使用 TPL 库重写它。下面的输出是我得到的(当然它是随机的)但是......我希望"完成!"总是最后打印。出于某种原因,它没有这样做。为什么不阻止?

Done!
1
0
2
6
5
4
3
7

使用 Task.WaitAll(线程)不会适当地阻塞

您没有将任何任务分配给要调用 WaitAll 的threads列表,您的任务是独立启动的。 在调用 WaitAll 之前,您将创建任务并将任务放入threads集合中。您可以在此 MSDN 文档中为 Task.WaitAll 方法 (Task[]) 找到如何在已创建的任务列表中添加任务的详细信息

你的代码会像

threads.Add(Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 10; i++) ;
}));

您没有将任务添加到线程集合中。所以线程集合是空的。所以没有任务要等待。像这样更改代码

threads.Add(Task.Factory.StartNew(() =>
    {
        for (int i = start; i < end; i++) body(i);
    }));
原因

很简单:您永远不会向threads列表中添加任何内容。您声明它并为numProcs条目分配空间,但从不调用threads.Add

因此,

列表仍然是空的,因此Task.WaitAll不会等待任何东西。