title: System.Progress not firing events on main thread after WinForms dialog was shown
body: <p>I have a WPF dialog that shows a progress meter control, and a background task (<a href="https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" rel="nofollow noreferrer"><code>System.Threading.Tasks.Task</code></a>) that provides a stream of progress updates that need to be fed into the progress meter. The mediator between the two is a <a href="https://msdn.microsoft.com/en-us/library/hh193692.aspx" rel="nofollow noreferrer"><code>System.Progress&lt;T&gt;</code></a> object.</p>
  
  <p>This all works perfectly under "normal" circumstances:</p>
  
  <ul>
  <li>The background task calls <code>System.IProgress.Report()</code> on some thread X that is not the main thread. </li>
  <li>The <code>System.Progress</code> object does its internal magic where it switches threads</li>
  <li>The <code>System.Progress</code> object fires the <code>ProgressChanged</code> event on the main thread.</li>
  <li>The progress meter control is updated on the main thread (which owns the control)</li>
  </ul>
  
  <p>Now, if I open <em>any</em> WinForms dialog, then close it, then start my background task, the <code>System.Progress</code> suddenly fires the <code>ProgressChanged</code> event not on the main thread, but on some thread Y that is not the main thread. This of course leads to an <code>InvalidOperationException</code> because the event handler tries to update the WPF progress meter control on a different thread than the one that owns the control.</p>
  
  <p>I noticed the docs for <code>System.Progress</code> saying that:</p>
  
  <blockquote>
    <p>[...] event handlers registered with the <code>ProgressChanged</code> event are invoked through a <a href="https://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx" rel="nofollow noreferrer"><code>SynchronizationContext</code></a> instance captured when the instance is constructed. If there is no current <a href="https://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx" rel="nofollow noreferrer"><code>SynchronizationContext</code></a> at the time of construction, the callbacks will be invoked on the <a href="https://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx" rel="nofollow noreferrer"><code>ThreadPool</code></a>.</p>
  </blockquote>
  
  <p>This seems to match what I can observe, because this is how the lower part of the call stack looks like when <code>System.Progress</code> fires its event in the bad case:</p>
  
  <pre><code>[...]
  bei System.Progress`1.InvokeHandlers(Object state)
  bei System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
  bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  bei System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
  bei System.Threading.ThreadPoolWorkQueue.Dispatch()
  bei System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
  </code></pre>
  
  <p>I checked the value of the <a href="https://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx" rel="nofollow noreferrer"><code>SynchronizationContext.Current</code></a> property at the time when the <code>System.Progress</code> object is created, but it is never null. The <code>SynchronizationContext</code> object returned by the property has the following types:</p>
  
  <ul>
  <li>Good case (i.e. before opening a WinForms dialog): The object is a <code>System.Windows.Forms.WindowsFormsSynchronizationContext</code></li>
  <li>Bad case (i.e. after opening a WinForms dialog): The object is a <code>System.Threading.SynchronizationContext</code></li>
  </ul>
  
  <p>Unfortunately I have not much experience with WinForms, and none at all with <code>SynchronizationContext</code>, so I am quite at a loss what is going on here.</p>
  
  <p>Why does opening a WinForms dialog change the <code>SynchronizationContext.Current</code> value? Why does this have an effect on how <code>System.Progress</code> behaves? Is there a way how to "fix" the problem, short of writing my own replacement of <code>System.Progress</code>?</p>
  
  <p><strong>EDIT:</strong> I might add that the executable is an MFC application at the core, the .exe project is compiled with /CLR, and the C# code that I am looking at is invoked via C++/CLI. The C# code is compiled for (and running under) .NET framework 4.5.1. The complicated setup is due to the application being a legacy beast with modern attitudes :-), but so far this has worked out very well for us.</p>