Task.Factory.StartNew and synchronization context
.net, asynchronous, c#, synchronizationcontext, task-parallel-library
Solution
The exact details of Win32 message pumping in the .NET framework are undocumented. Note that the Win32 API has historically permitted reentrant behavior.
When your code starts the task, the task scheduler it's using will request the task to execute on the current `SynchronizationContext`. So it ends up calling `SynchronizationContext.Current.Post`, very similar to your second code example.
The `WindowsFormsSynchronizationContext` works by posting a Win32 message to the message queue; the message type is one defined internally by .NET to mean "execute this code". (These details are undocumented).
When your code proceeds to call `MessageBox.Show`, it runs a nested message loop, and that is why the queued actions are executing. If you removed the `Exit!` message box, then the actions would execute after `Form1_Load` returns to the top-level message loop in `Application.Run`.
Problem
A simple question. Here is a part of a WinForms app: ``` void Form1_Load(object sender, EventArgs e) { var task2 = Task.Factory.StartNew(() => MessageBox.Show("Task!"), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); Debug.WriteLine("Before Exit"); MessageBox.Show("Exit!"); } ``` Could someone please explain why I see "Task!" first, and then "Exit" when I run this? And when I see the "Task!" message box, "Before Exit" has been already printed in the debug output. EDIT: More simple, same effect: ``` void Form1_Load(object sender, EventArgs e) { SynchronizationContext.Current.Post((_) => MessageBox.Show("Task!"), null); Debug.WriteLine("Before Exit"); MessageBox.Show("Exit!"); } ``` EDIT: If I replace `MessageBox.Show("Exit!")` with `Form { Text = "Exit!" }.ShowDialog()`, I see "Exit", then "Task", as expected. Why is that?