title: task.Wait throwing an exception
body: <p>Largely as a follow-up to this question <a href="https://stackoverflow.com/questions/4380732/test-driven-asynch-tasks">test driven asynch tasks</a> I have come up with some code that works if I don't have the task wait, but fails if I do.</p>
  
  <p>Can anyone explain why?</p>
  
  <p><strong>Exception:</strong></p>
  
  <p>I get this error when the code hits the constructor of a utility class written by Stephen Cleary on his blog <a href="http://nitoprograms.blogspot.com/2010/06/reporting-progress-from-tasks.html" rel="nofollow noreferrer">here</a></p>
  
  <pre><code>public ProgressReporter()
  {
      _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
  }
  
  Test 'Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.OnSuccessFullComplete_ExpectedResultIsReturned_JustWait' failed:
  System.AggregateException : One or more errors occurred.
  ----&gt; System.InvalidOperationException : The current SynchronizationContext may not be used as a TaskScheduler.
  at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
  at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
  at System.Threading.Tasks.Task.Wait()
  Threading\ProgressReporterTests.cs(142,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.OnSuccessFullComplete_ExpectedResultIsReturned_JustWait()
  --InvalidOperationException
  at System.Threading.Tasks.SynchronizationContextTaskScheduler..ctor()
  at System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext()
  Threading\ProgressReporter.cs(24,0): at Smack.Core.Lib.Threading.ProgressReporter..ctor()
  Threading\ProgressReporterTests.cs(52,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests._startBackgroundTask(Boolean causeError)
  Threading\ProgressReporterTests.cs(141,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.&lt;OnSuccessFullComplete_ExpectedResultIsReturned_JustWait&gt;b__a()
  at System.Threading.Tasks.Task.InnerInvoke()
  at System.Threading.Tasks.Task.Execute()
  </code></pre>
  
  <p><strong>The test (NUnit w/ TestDriven.Net runner):</strong></p>
  
  <pre><code>private class MockSynchContext : SynchronizationContext{}
  
  [Test]
  public void OnSuccessFullComplete_ExpectedResultIsReturned_Wait()
  {
      var mc = new MockSynchContext();
      SynchronizationContext.SetSynchronizationContext(mc);
      Assert.That(SynchronizationContext.Current, Is.EqualTo(mc));
      Assert.DoesNotThrow(() =&gt; TaskScheduler.FromCurrentSynchronizationContext());
      var task = Task.Factory.StartNew(() =&gt; _startBackgroundTask(false));
      task.Wait(2000);
      _actualResult = 42;
  }
  </code></pre>
  
  <p><strong>The SuT:</strong></p>
  
  <pre><code>private void _startBackgroundTask(bool causeError)
  {
      _cancellationTokenSource = new CancellationTokenSource();
      var cancellationToken = _cancellationTokenSource.Token;
      _progressReporter = new ProgressReporter();
      var task = Task.Factory.StartNew(() =&gt;
              {
                  for (var i = 0; i != 100; ++i) {
                      // Check for cancellation 
                      cancellationToken.ThrowIfCancellationRequested();
  
                      Thread.Sleep(30); // Do some work. 
  
                      // Report progress of the work. 
                      _progressReporter.ReportProgress(
                          () =&gt;
                              {
                                  // Note: code passed to "ReportProgress" can access UI elements freely. 
                                  _currentProgress = i;
                              });
                  }
  
                  // After all that work, cause the error if requested.
                  if (causeError) {
                      throw new InvalidOperationException("Oops...");
                  }
  
  
                  // The answer, at last! 
                  return 42;
              },
          cancellationToken);
  
      // ProgressReporter can be used to report successful completion,
      //  cancelation, or failure to the UI thread. 
      _progressReporter.RegisterContinuation(task, () =&gt;
      {
          // Update UI to reflect completion.
          _currentProgress = 100;
  
          // Display results.
          if (task.Exception != null)
              _actualErrorMessage = task.Exception.ToString();
          else if (task.IsCanceled)
              _wasCancelled = true;
          else 
              _actualResult = task.Result;
  
          // Reset UI.
          _whenCompleted();
      });
  }
  </code></pre>
  
  <p><strong>Just to be clear:</strong> If I comment out task.Wait, that test actually succeeds. Why is that?</p>
  
  <p><strong>Extra points:</strong></p>
  
  <p>I know this is technically another question but it seems a shame to repeat all of this, so:</p>
  
  <p>Why did my MockSynchContext not throw an exception on TaskScheduler.FromCurrentSynchronizationContext() in my test but did in the second task? More importantly, is there a way to pass the context along so I can do the test properly?</p>