Reputation: 1578
I have the following winforms event
public MainForm()
{
InitializeComponent();
new Form().ShowDialog(); // This causes the problem
}
private async void MainForm_Load(object sender, EventArgs e)
{
LoadingLabel.Text = "Initializing...";
try
{
await Task.Delay(500);
}
catch (Exception ex)
{
MessageBox.Show("Error initializing");
Environment.Exit(0);
}
Console.WriteLine(LoadingLabel.InvokeRequired);
}
Expectation: Program prints false
.
Result: Program prints true
.
It is my understanding that await should set the synchronization context back to the original and no Invoke
should be required. However, this is not the case. Attempting to update LoadingLabel
's Text
property throws an InvalidOperationException
. Am I missing something?
I am using .NET 4.5.2.
Upvotes: 3
Views: 573
Reputation: 7091
After the call to ShowDialog
, which creates a nested message loop the WindowsFormsSyncronizationContext
is replaced with the default SyncronizationContext
causing you to need an Invoke
. The context is then later restored. Further reading How to get a Synchronization Context for the second form shown
You have some options:
(1) Structure your code so that the call to ShowDialog
occurs in the Load
event or in the OnLoad override
. I think this is the best approach and would serve you well long term.
(2) However, you can also do this:
public MainForm() {
InitializeComponent();
var uiContext = SynchronizationContext.Current;
new Form().ShowDialog();
SynchronizationContext.SetSynchronizationContext(uiContext);
}
This simply resets the SyncronizationContext
back when the dialog is closed.
Upvotes: 2