Task.Faulted和Task.Exception
TaskStatus Enum或Task.Exception MSDN似乎都没有明确表示:
TasksStatus.Faulted
总是暗示Task.Exception != null
(和TaskStatus != Faulted
Task.Exception == null
总是暗示Task.Exception == null
)?
是的, Task.IsFaulted的文档明确指出:
如果IsFaulted为true,则任务的Status将等于Faulted,并且其Exception属性将为非null。
参考源代码确实列出了几乎可以肯定的。 在FinishStageTwo
我们看到内部FinishStageTwo
仅在记录的exception时设置为出错:
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 (ie, 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);
如果您已经完成等待任务完成,第一种情况也永远不会失败。 这可能就是为什么他们将其标记为“仁慈”并将其留在原因中。受其影响的代码量非常小。