2016-02-23 42 views
0

我需要调用Task对象的操作方法。我的任务执行某种阅读,如果完成时间超过2秒,我会取消操作。任务状态值为Faulted取消

我有这样的代码模拟:

var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(2000)); 

    var task = Task.Run(() => 
    { 
     try 
     { 
      int i = 0; 

      while (true) 
      { 
       Thread.Sleep(500); 

       cts.Token.ThrowIfCancellationRequested(); 

       Console.WriteLine("i = {0}", i); 
       i++; 

       if (i > 3) throw new InvalidOperationException(); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Exception {0}", e.Message); 
      throw; 
     } 
    }); 

    task.ContinueWith(t => Console.WriteLine(t.Status), TaskContinuationOptions.NotOnRanToCompletion); 

我的控制台outout如下:

enter image description here

这是我期待和我的作品。如果我将代码复制到任务中并创建一个方法,我不再将任务状态视为已取消。我的状态为Faulted。我必须知道在阅读过程中操作是否被取消或发生异常。我无法弄清楚为什么我没有在这里取消任务状态。

var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(2000)); 

    var task = Task.Run(() => 
    { 
     try 
     { 
      Tester(cts); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Exception {0}", e.Message); 
      throw; 
     } 
    }); 

private static void Tester(CancellationTokenSource cts) 
{ 
    int i = 0; 

    while (true) 
    { 
     Thread.Sleep(500); 

     cts.Token.ThrowIfCancellationRequested(); 

     Console.WriteLine("i = {0}", i); 
     i++; 

     if (i > 3) throw new InvalidOperationException(); 
    } 
} 

enter image description here

回答

1

你得到预期Canceled因此,如果您通过令牌Task.Run

var task = Task.Run(() => 
{ 
    try 
    { 
     Tester(cts); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine("Exception {0}", e.Message); 
     throw; 
    } 
}, cts.Token); 

任务需要知道哪些令牌将抛出OperationCanceledException - 唯一的例外来自正确的来源取消任务,其他任何异常都会使其失败。

MSDN

当一个任务实例观察到用户代码抛出OperationCanceledException,它异常的令牌进行比较,确认相关的令牌(传递给创建任务的API的一个)。如果它们相同,并且标记的IsCancellationRequested属性返回true,则该任务将此解释为确认取消并转换为取消状态。

我不完全理解为什么你在第一时间获得Canceled结果,它看起来像它具有当CancellationTokenSource捕获与做。

+0

前段时间我花了一些时间找到相同的原因。是的,传递令牌解决了问题。谢谢你的答案。 – Demir