【问题标题】:Task.WaitAll Method (Task[], Int32) doesn't release the thread when it is expiredTask.WaitAll Method (Task[], Int32) 线程过期不释放
【发布时间】:2014-09-03 14:10:32
【问题描述】:

Task.WaitAll Method (Task[], Int32) 线程过期不释放。

我正在使用.net 框架 4.0。 我发现Task.WaitAll Method过期后仍然占用线程。

我写下面的代码来测试它。

static void Main(string[] args)
        {
            printThreadCount("start");
            Task[] tasks = new Task[5];
            for (int i = 0; i < 5; i++)//create tasks
            {
                Task t = new Task(() =>
                {
                    Thread.Sleep(30000);
                    Console.WriteLine(DateTime.Now.ToString() + "task finish");
                }
               );

               tasks[i] = t;
            }

            for (int i = 0; i < 5; i++)
            {
                tasks[i].Start();//start 1 task per second
                Thread.Sleep(1000);
                printThreadCount("start 1 task per second");
            }

            printThreadCount("before waitall");
            Task.WaitAll(tasks, 10000);

            printThreadCount("after waitall 10s");
            Thread.Sleep(5000);
            printThreadCount("sleep 5s");
            Thread.Sleep(5000);
            printThreadCount("sleep 5s");
            Thread.Sleep(5000);
            printThreadCount("sleep 5s");
            Thread.Sleep(5000);
            printThreadCount("sleep 5s");

            Console.WriteLine("end");
        }

        static void printThreadCount(string title)
        {
            int MaxWorkerThreads, MaxIOThreads;
            ThreadPool.GetMaxThreads(out MaxWorkerThreads, out MaxIOThreads);
            int AvailableWorkerThreads = 0;
            int AvailableIOThreads = 0;
            ThreadPool.GetAvailableThreads(out AvailableWorkerThreads, out AvailableIOThreads);

            Console.WriteLine();
            Console.WriteLine("*****************" + title + "********************");

            Console.WriteLine("active Worker Threads count:" + (MaxWorkerThreads - AvailableWorkerThreads));
            Console.WriteLine("active IO Threads count:" + (MaxIOThreads - AvailableIOThreads));
        }

我创建了 5 个任务,每秒启动 1 个任务,每个任务将持续 30 秒。 Task.WaitAll 将等待它们 10 秒。 理想情况下,当 waitall 过期时,它们都超时。但他们仍然占据着主线。足够的时间后,所有任务将完成并运行Console.WriteLine(DateTime.Now.ToString() + "task finish"),然后释放所有线程。

结果如下:

这对我来说不是正常行为。我希望时间结束后所有任务都被杀死。 waitall时间到了怎么杀掉??

【问题讨论】:

    标签: c# multithreading task-parallel-library clr threadpool


    【解决方案1】:

    我希望时间结束后所有任务都被杀死。

    documentation 可以看出,Task.WaitAll 不会杀死 任务。它只是等待他们完成最多 10 秒。如果它们没有在 10 秒内完成,则该方法返回并且什么也不做。

    如果你想取消你的任务,你应该使用CancellationToken。见Cancellation in Managed Threads

    //create a cancellation token that will cancel itself after 3secs
    int timeout = 3000;
    var source = new CancellationTokenSource(timeout);
    var token = source.Token;
    
    List<Task> tasks = new List<Task>();
    for (int i = 0; i < 5; i++)
    {
        Task t = Task.Run(async () =>
            {
                //wait for 30 secs OR until cancellation is requested
                await Task.Delay(30000, token);
                Console.WriteLine(DateTime.Now.ToString() + "task finish");
            });
        tasks.Add(t);
    }
    
    printThreadCount("before waitall");
    try
    {
        Task.WaitAll(tasks.ToArray());
    }
    catch(AggregateException ex)
    {
        foreach (var e in ex.Flatten().InnerExceptions)
            Console.WriteLine(e.Message);
    }
    printThreadCount("after waitall");
    

    【讨论】:

    • 事实上甚至不可能杀死任意任务。
    • @usr 没错,这似乎是 OP 所期望的。是否包含取消逻辑取决于程序员,CancellationTokens 让这项工作变得更容易。
    猜你喜欢
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 2021-03-27
    • 1970-01-01
    • 2016-03-05
    • 2011-09-13
    • 1970-01-01
    相关资源
    最近更新 更多