Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Faulted and Task.Exception

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

like image 656
Ricibob Avatar asked Aug 28 '15 14:08

Ricibob


1 Answers

Yes, the documentation for Task.IsFaulted explicitly states that:

If IsFaulted is true, the task's Status is 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 were 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.

like image 50
shf301 Avatar answered Oct 06 '22 06:10

shf301