2014-07-13 3 views
2

Task.WaitAll 메서드 (작업 [], Int32) 만료되면 스레드를 해제하지 않습니다.Task.WaitAll 메서드 (작업 [], Int32) 만료되면 스레드를 해제하지 않습니다.

저는 using.net 프레임 워크 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 시간이 만료되었을 때 그들을 죽이는 방법 ??

답변

4

시간이 끝나면 모든 작업을 중단하고 싶습니다.

당신이 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"); 
+0

실제로 임의의 작업을 죽이는 것도 불가능합니다. – usr

+1

@usr 정확히, 그리고 그것이 OP가 일어날 것으로 예상되는 것으로 보입니다. 프로그래머는 취소 로직을 포함해야하며,'CancellationToken'은 그 일을 더 쉽게 만듭니다. – dcastro