async/await可以更新UI线程,但还是有一定问题存在,比如如下情况会造成死锁。
遇到的问题:
private void button1_Click(object sender, EventArgs e) {
Task<string> res = GetResAsync();
textBox1.Text = res.Result;
}
private async Task<string> GetResAsync() {
string t = await Task.Run(() => {
Thread.Sleep(1000);
return "返回结果";
});
return t;
}
只要点击button就会造成线程死锁,原因:
await时会获取当前线程的SychronizationContext,而res.Result等待await执行完成,await等待获取SychronizationContext,造成死锁
解决方案1:在await前就把SychronizationContext获取了
缺点:
1、res.Result时会等待,容易造成界面无响应
2、SetSynchronizationContext(null)容易出现副作用
private void button1_Click(object sender, EventArgs e) {
Task<string> res = GetResAsync();
textBox1.Text = res.Result;
}
private async Task<string> GetResAsync() {
//获取当前线程的SychronizationContext
SynchronizationContext syncContext = WindowsFormsSynchronizationContext.Current;
//设置当前线程的SychronizationContext为null
WindowsFormsSynchronizationContext.SetSynchronizationContext(null);
string t = await Task.Run(() => {
Thread.Sleep(1000);
return "返回结果";
});
//设置当前线程的SychronizationContext
WindowsFormsSynchronizationContext.SetSynchronizationContext(syncContext);
return t;
}
解决方案2:再套一层Task.Run
缺点:
1、res.Result时会等待,容易造成界面无响应
2、await无法直接更新UI界面
private void button1_Click(object sender, EventArgs e) {
Task<string> res = Task.Run(GetResAsync);
textBox1.Text = res.Result;
}
private async Task<string> GetResAsync() {
string t = await Task.Run(() => {
Thread.Sleep(1000);
return "返回结果";
});
return t;
}
版权声明:本文为qq_42690327原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。