為什麼 SynchronizationContext 如此重要

考慮這個例子:

private void button1_Click(object sender, EventArgs e)
{
    label1.Text = RunTooLong();
}

此方法將凍結 UI 應用程式,直到 RunTooLong 完成。該應用程式將無響應。

你可以嘗試非同步執行內部程式碼:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() => label1.Text = RunTooLong());
}

但是這段程式碼不會執行,因為內部主體可能在非 UI 執行緒上執行,它不應該直接更改 UI 屬性

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() =>
    {
        var label1Text = RunTooLong();

        if (label1.InvokeRequired)
            lable1.BeginInvoke((Action) delegate() { label1.Text = label1Text; });
        else
            label1.Text = label1Text;
    });
}

現在不要忘記總是使用這種模式。或者,試試 SynchronizationContext.Post ,它會為你做到:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() =>
    {
        var label1Text = RunTooLong();
        SynchronizationContext.Current.Post((obj) =>
        {
            label1.Text = label1    Text);
        }, null);
    });
}