2013-09-25 55 views
1

我需要取消未决任务并等待其终止代码流才能继续。通常情况下,我这样做:取消任务并等待终止的选项

if (this.task != null) 
{ 
    this.taskCancellationTokenSource.Cancel(); 
    try 
    { 
     await this.task; 
     // I don't need to know the result, just log it 
     Debug.Print(this.task.Status.ToString()); 
    } 
    catch (Exception e) 
    { 
     // I don't need to know the result, just log it 
     Debug.Print(e.ToString()); 
    } 
} 

我才意识到我可以做同样的无try/catch

if (this.task != null) 
{ 
    this.taskCancellationTokenSource.Cancel(); 
    await this.task.ContinueWith(
     // I don't need to know the result, just log it 
     (t) => Debug.Print(((object)t.Exception ?? (object)t.Status).ToString()), 
     TaskContinuationOptions.ExecuteSynchronously) 
} 

我失去了任何理由,我应该坚持第一种方法?

回答

2

我错过了我应该坚持第一种方法的任何理由吗?

两个原因,把我的头顶部:

  1. ContinueWith将默认使用当前的调度,这可能会导致并发问题或令人惊讶的行为。
  2. 当您阅读Task.Exception属性时,先行任务(在您的示例中为t)将包含AggregateException中的任何异常。

我推荐使用await而不是ContinueWith,因为它在这两种情况下都具有更合理的行为。 await将捕获当前上下文并使用它来安排延续,并且await将不会在AggregateException中包装例外。

如果你确实使用ContinueWith,那么你应该总是明确地指定一个TaskScheduler来继续运行。

+0

谢谢斯蒂芬。我期望上面的代码中的'ContinueWith'始终与它的先行任务在同一个线程和上下文中运行 - 同步,因为有'TaskContinuationOptions.ExecuteSynchronously'。我的测试总是如此。这是错误的假设吗? – Noseratio

+1

'ExecuteSynchronously'是一个提示。有[在某些情况下,它不被尊重](http://blogs.msdn.com/b/pfxteam/archive/2012/02/07/10265067.aspx)。 –

+0

伟大的信息。这些案例本来很难调试。 – Noseratio