问题
Neither TaskStatus Enum or Task.Exception MSDN appear to state explicity:
Does TasksStatus.Faulted ALWAYS imply Task.Exception != null (and TaskStatus != Faulted always imply Task.Exception == null)?
回答1:
Yes the documentation for Task.IsFaulted explicitly states that:
If IsFaulted is true, the task's Status will be equal to Faulted, and its Exception property will be non-null.
The reference source code does list the as an almost certainly. In FinishStageTwo we see that the internal m_state is only set to faulted if exceptions where recorded:
if (ExceptionRecorded)
{
completionState = TASK_STATE_FAULTED;
...
}
...
Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState);
So the state will only be faulted if exceptions were recorded.
However Exception getter does mention a possible race condition:
// 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).
This race condition will only occur if IsFaulted becomes true as Exception getter is running.
So the following code could fail if called while the task is executing:
var ex = task.Exception;
var faulted = task.IsFaulted;
if (faulted)
Assert.IsTrue(ex != null);
However the following will never fail:
var faulted = task.IsFaulted;
var ex = task.Exception;
if (faulted)
Assert.IsTrue(ex != null);
The first case will also never fail if you've already finished waiting for the task to complete. That's probably why they labeled it as "benevolent" and left it in. The amount of code that would be affected by it is pretty small.
来源:https://stackoverflow.com/questions/32273165/task-faulted-and-task-exception