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

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

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

我使用的是 .net framework 4.0。 我发现 Task.WaitAll 方法在过期时仍然占用线程。

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

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"),然后释放所有线程。

结果如下:

the result of above code

这对我来说不是正常行为。我希望时间结束时所有任务都被杀死。 如何在 waitall 时间到期时杀死它们??

最佳答案

I want all the task are killed when time is over.

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");

关于c# - Task.WaitAll Method (Task[], Int32) 过期不释放线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24723338/

相关文章:

c# - 如何声明类的 List 属性的获取和设置访问器

C# 垃圾回收

c# - 使用 FindControl (""的简单方法)

C++ 多线程 : Do I need mutex for constructor and destructor?

.net - Rx .NET : Filter observable until task is done

c# - await Task.Delay 花费的时间比预期的要长

c# - Task.StartNew() 在 STA 模式下的工作方式不同?

c# - ASP.NET MVC 3 + Razor 错误 : Child actions are not allowed to perform redirect actions

c# - 如果引发任何异常,如何在 Task.WhenAll 上取消并引发异常?

c# - 在 C# 中检查堆栈大小