TaskDialog.ShowDialog() doesn't install WindowsFormsSynchronizationContext
See original GitHub issue-
.NET Core Version: 5.0.100-preview.5.20255.2
-
Have you experienced this same bug with .NET Framework?: No
Problem description:
Currently, TaskDialog.ShowDialog() doesn’t install the WindowsFormsSynchronizationContext, so when showing the task dialog from a thread that didn’t call a Control constructor and which currently isn’t running a message loop e.g. with Form.ShowDialog() or Application.Run(), continuations of async methods that were initiated from an task dialog event won’t run on the same thread used to show the task dialog.
Expected behavior:
I think TaskDialog.ShowDialog should install the WindowsFormsSynchronizationContext before actually showing the dialog if SynchronizationContext.Current isn’t an WindowsFormsSynchronizationContext, and in that case, should also uninstall it after the native TaskDialogIndirect returns.
Note: It seems MessageBox.Show() also doesn’t install the WindowsFormsSynchronizationContext, but there it’s probably not that important since yout normally don’t handle events within MessageBox.Show().
What do you think?
Minimal repro:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
var mainThread = Thread.CurrentThread;
var myPage = new TaskDialogPage();
myPage.Created += async (s, e) =>
{
Console.WriteLine("TaskDialog.ShowDialog():");
Console.WriteLine("Is WindowsFormsSynchronizationContext: " +
(SynchronizationContext.Current is WindowsFormsSynchronizationContext));
await Task.Yield();
Console.WriteLine("Is Main Thread: " + (Thread.CurrentThread == mainThread));
Console.WriteLine();
myPage.BoundDialog!.Close();
};
TaskDialog.ShowDialog(myPage);
using var myForm = new Form();
myForm.Load += async (s, e) =>
{
Console.WriteLine("Form.ShowDialog():");
Console.WriteLine("Is WindowsFormsSynchronizationContext: " +
(SynchronizationContext.Current is WindowsFormsSynchronizationContext));
await Task.Yield();
Console.WriteLine("Is Main Thread: " + (Thread.CurrentThread == mainThread));
Console.WriteLine();
myForm.Close();
};
myForm.ShowDialog();
}
Actual output:
TaskDialog.ShowDialog():
Is WindowsFormsSynchronizationContext: False
Is Main Thread: False
Form.ShowDialog():
Is WindowsFormsSynchronizationContext: True
Is Main Thread: True
Expected output:
TaskDialog.ShowDialog():
Is WindowsFormsSynchronizationContext: True
Is Main Thread: True
Form.ShowDialog():
Is WindowsFormsSynchronizationContext: True
Is Main Thread: True
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:18 (18 by maintainers)

Top Related StackOverflow Question
AFAIK, TaskDialog is not a COM API. It’s a regular function
TaskDialogIndirectincomctl32.dll.(The documentation says that TaskDialog requires the single-threaded apartment (STA) model, but I didn’t experience any problems yet when showing the task dialog from threads using the MTA model. When I call
GetWindowThreadProcessIdwith the task dialog handle from an MTA thread, it returns the same value asGetCurrentThreadId.)Thank you!
I’ve thought about it and think I like option (2) from my previous post most currently. The
TaskDialogconstructor -not ShowDialog- should do the same work theControlconstructor does, installing a WFSC by calling InstallIfNeeded (but not uninstalling it once its done, since Controls don’t do that either).This strategy of treating it like a Control as far as WinForms initialization is concerned should not introduce any new behavior and keep the risk minimal:
this makes TaskDialog just another variant of the existing code paths.
It doesn’t solve the shutdown problems but I think those are out of scope of this issue, if someone is to approach WFSC shutdown to make it more async-friendly it needs to be its own issue and be done across whole WinForms and not just one usecase like here.
Office integration can be treated similar to MessageBox, since (I assume, didn’t check) the message loop of TaskDialog is win32 and not WinForms it might be hard to negotiate the IMsoComponent state.
Sorry if I’m ranting a bit, got surprised by this issue and I’ve not got the time to think everything through before I wrote my first posts.