winforms事件中未保留同步上下文

时间:2017-04-05 01:20:54

标签: c# winforms async-await

我有以下winforms事件

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);
}

期望:程序打印false 结果:程序打印true

据我了解,await应该将同步上下文设置回原始状态,并且不需要Invoke。然而,这种情况并非如此。尝试更新LoadingLabel的{​​{1}}属性会引发Text。我错过了什么吗?

我使用的是.NET 4.5.2。

1 个答案:

答案 0 :(得分:1)

在调用ShowDialog后,会创建一个嵌套的消息循环,WindowsFormsSyncronizationContext将替换为默认的SyncronizationContext,导致您需要Invoke。然后恢复上下文。进一步阅读How to get a Synchronization Context for the second form shown

你有一些选择:

(1)构建代码,以便在ShowDialog事件或Load中调用OnLoad override。我认为这是最好的方法,可以长期为您服务。

(2)但是,您也可以这样做:

public MainForm() {
    InitializeComponent();
    var uiContext = SynchronizationContext.Current;
    new Form().ShowDialog();
    SynchronizationContext.SetSynchronizationContext(uiContext);
}

当对话框关闭时,这会简单地重置SyncronizationContext