的任务.Faulted和Task.Exception

本文关键字:Task Exception Faulted 任务 | 更新日期: 2023-09-27 18:10:11

TaskStatus Enum和Task均无。异常MSDN显示显式状态:

TasksStatus.Faulted总是暗示Task.Exception != null(和TaskStatus != Faulted总是暗示Task.Exception == null)?

的任务.Faulted和Task.Exception

是的,任务的文档。IsFaulted明确声明:

如果IsFaulted为true,则该任务的Status等于Faulted,且其Exception属性为非空。

参考源代码确实将其列为几乎肯定的。在FinishStageTwo中,我们看到内部m_state只有在记录异常时才被设置为faulted:

  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).

只有当Exception getter正在运行时,IsFaulted变为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);

如果您已经完成了等待任务完成,那么第一个case也永远不会失败。这可能就是为什么他们给它贴上"仁慈"的标签;然后把它留在里面。受此影响的代码量非常小。