2012-08-26 73 views
3

我已经写了下面的代码:任务状态时取消

CancellationTokenSource tokenSource = new CancellationTokenSource(); 
CancellationToken token = tokenSource.Token; 

int i = 0; 
Console.WriteLine("Calling from Main Thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId); 

Task t1 = new Task(() => 
{ 
    while (true) 
    { 
     try 
     { 
      token.ThrowIfCancellationRequested(); 
     } 

     catch (OperationCanceledException) 
     { 
      Console.WriteLine("Task1 cancel detected"); 
      break; 
     } 

     Console.WriteLine("Task1: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++); 
    } 
}, token); 

Task t2 = new Task(() => 
{ 
    while (true) 
    { 
     try 
     { 
      token.ThrowIfCancellationRequested(); 
     } 

     catch (OperationCanceledException) 
     { 
      Console.WriteLine("Task2 cancel detected"); 
      break; 
     } 

     Console.WriteLine("Task2: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++); 
    } 
}); 

t1.Start(); 
t2.Start(); 
Thread.Sleep(100); 
tokenSource.Cancel(); 

t1.Wait();//wait for thread to completes its execution 
t2.Wait();//wait for thread to completes its execution 
Console.WriteLine("Task1 Status:{0}", t1.Status); 
Console.WriteLine("Task2 Status:{0}", t1.Status); 

我在这里取消接任务也状态显示RanToCompletion,但如果我在两个任务删除的等待,那么就说明我取消状态.. 。

因为我取消了任务,我期待在任何情况下,取消状态...

编辑:从MSDN 通过投掷OperationCanceledException并将其传递次请求取消的令牌。执行此操作的首选方法是使用ThrowIfCancellationRequested方法。以这种方式取消的任务转换为取消状态,调用代码可以使用该状态来验证任务是否响应了取消请求。

如果不使用等待或为WaitAll方法来等待任务,该任务只是将其地位已取消。

回答

6

当你正赶上OperationCanceledException并打破while循环,任务结束优雅和任务状态会RanToCompletion。

为了得到一个取消状态,你要么需要重新抛出OperationCanceledException或抓不住它。

任务用自己的的CancellationToken抛出 OperationCanceledException承认取消而 令牌是信号状态,或任务的的CancellationToken是 不已:当

根据MSDN任务状态将被取消在任务开始执行之前发出信号。有关更多 的信息,请参见Task Cancellation

由于您已经吞下源代码中的异常,因此任务状态将为RanToCompletion。

要获得关于为什么当你删除等待状态被取消的问题,很可能是因为异常尚未捕获,并且取消状态已经在较早时间得到遏制。 此行为不应被视为可靠和可重复。

+0

感谢齐亚德。但是,当我删除的任务,然后我得到它正在创造一些混乱的取消状态等待.. –

+0

更新从MSDN链接的问题:仍然搞不清我已经更新了声明。它是否与你最后的陈述相矛盾? –

+0

@RaoBHavik我认为当您执行Wait时状态为Cancelled的事实完全是巧合。实际上,如果您替换Thread.Sleep(5000)这两个等待,任务状态可能会是RanToCompletion。 –