為什麼 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);
});
}