roa*_*oul 2 c# clr multithreading threadpool task-parallel-library
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));
}
Run Code Online (Sandbox Code Playgroud)
我创建了5个任务,每秒启动1个任务,每个任务将持续30秒.而Task.WaitAll将等待他们10秒钟.理想情况下,当waitall过期时,所有这些都是超时.但他们仍占据着主线.经过足够的时间,所有任务都将完成并运行 Console.WriteLine(DateTime.Now.ToString() + "task finish")
,然后释放所有线程.
结果如下:
这对我来说不是一个正常的行为.我希望所有的任务都在时间结束时被杀死.等待时间到期后如何杀死它们?
我希望所有的任务都在时间结束时被杀死.
从文档中可以看出,Task.WaitAll
不会杀死任务.它只是等待它们最多完成10秒.如果它们没有在10秒内完成,则该方法返回并且不再执行任何操作.
如果你想取消你的任务,你应该使用CancellationToken
.请参阅托管线程中的取消
//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");
Run Code Online (Sandbox Code Playgroud)