2

Task.WaitAll Method (Task[], Int32) doesn't release the thread when it is expired.

I'm using.net framework 4.0. I find that Task.WaitAll Method still occupy the thread when it's expired.

I write below code to test it.

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

I create 5 tasks,and start 1 task per second, each task will last 30 seconds. And Task.WaitAll will wait them for 10 seconds. Ideally, when the waitall expired, all of them are timeout. But they still occupy the thread. After enough time, all the task will finish and run Console.WriteLine(DateTime.Now.ToString() + "task finish"), then all the threads are released.

The result is as follow:

the result of above code

That's not a normal behavior for me. I want all the task are killed when time is over. How to kill them when the waitall time is expired??

svick
  • 236,525
  • 50
  • 385
  • 514
roast_soul
  • 3,554
  • 7
  • 36
  • 73

1 Answers1

5

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

As you can see from the documentation, Task.WaitAll does not kill the tasks. It simply waits for them to complete for 10secs max. If they don't complete within 10secs, the method returns and does nothing more.

If you want to cancel your tasks, you should be using a CancellationToken. See 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");
dcastro
  • 66,540
  • 21
  • 145
  • 155
  • In fact it is not even possible to kill arbitrary tasks. – usr Jul 13 '14 at 14:54
  • 1
    @usr Exactly, and that seemed to be what the OP expected to happen. It's up to the programmer to include cancellation logic, and `CancellationToken`s make that job easier. – dcastro Jul 13 '14 at 14:55