C# Task.Faulted和Task.Exception

C# Task.Faulted和Task.Exception,c#,task-parallel-library,task,C#,Task Parallel Library,Task,或MSDN均未明确说明: TasksStatus.Faulted是否总是意味着Task.Exception!=null(和TaskStatus!=出现故障始终意味着Task.Exception==null) 是的,的文档明确指出: 如果IsFaulted为true,则任务的状态等于Faulted,其Exception属性将为非null 参考源代码几乎可以肯定地列出了。在finishstagewo中,我们看到只有在记录异常时,内部m_状态才会设置为故障: if (ExceptionRecord

或MSDN均未明确说明:


TasksStatus.Faulted
是否总是意味着
Task.Exception!=null
(和
TaskStatus!=出现故障
始终意味着
Task.Exception==null

是的,的文档明确指出:

如果IsFaulted为true,则任务的状态等于Faulted,其Exception属性将为非null

参考源代码几乎可以肯定地列出了。在
finishstagewo
中,我们看到只有在记录异常时,内部
m_状态
才会设置为故障:

  if (ExceptionRecorded)
  {
      completionState = TASK_STATE_FAULTED;
      ...
  }
  ...
  Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState);
因此,只有记录了异常时,状态才会出现故障

然而,
Exception
getter确实提到了一个可能的竞争条件:

// Only return an exception in faulted state (skip manufactured exceptions)
// A "benevolent" race condition makes it possible to return null when IsFaulted is
// true (i.e., if IsFaulted is set just after the check to IsFaulted above).
只有当
IsFaulted
在运行
Exception
getter时变为true时,才会出现此争用条件

因此,如果在任务执行时调用,以下代码可能会失败:

 var ex = task.Exception;
 var faulted = task.IsFaulted;
 if (faulted)
     Assert.IsTrue(ex != null);
但是,以下方面永远不会失败:

 var faulted = task.IsFaulted;
 var ex = task.Exception;
 if (faulted)
     Assert.IsTrue(ex != null);

如果您已经完成了等待任务完成的任务,那么第一个案例也永远不会失败。这可能就是为什么他们把它贴上“仁慈”的标签,并把它放在里面。受其影响的代码量非常少。

只需检查Task.Status是如何在上实现的。它很复杂,但更准确。Tks-源代码很有趣。有一个内部异常记录(带有注释“以前称为IsFaulted的属性”)-用于检查记录的异常。有IsFaulted检查(m_stateFlags&TASK_STATE_FAULTED)和Status检查与IsFaulted完全相同。因此,从代码上看,它不那么清晰——它当然不像检查记录的异常那样简单!@qxg建议的代码源并不像Task.IsFaulted上的文档看起来那样令人信服和清晰。