我有一个按钮和一个标签WinForms应用程序以下代码:访问UI控件在Task.Run与异步/等待上的WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
await Run();
}
private async Task Run()
{
await Task.Run(async() => {
await File.AppendText("temp.dat").WriteAsync("a");
label1.Text = "test";
});
}
}
}
这是实际应用I”的一个简化的版本正在努力。我的印象是,通过在我的Task.Run
中使用async/await,我可以设置label1.Text
属性。但是,运行此代码时,我得到错误信息,说明我不在UI线程中,并且无法访问该控件。
为什么我不能访问标签控件?
您不应该使用GUI同步上下文中的异步无效方法。 C.F. http://msdn.microsoft.com/en-us/magazine/jj991977.aspx - “GUI和ASP.NET应用程序有一个SynchronizationContext,一次只允许运行一个代码块。当await完成时,它尝试在捕获的上下文中执行异步方法的其余部分,但该上下文已经有一个线程,它正在(同步)等待异步方法完成,它们都在等待另一个,导致死锁。 – Daniel
@Daniel这个引用是关于异步代码的同步等待(例如'Wait()'),我当然不会这么说。从同一篇文章:“无效返回异步方法有一个特定的目的:使异步事件处理程序成为可能。”这正是我在这里做的。 – svick
值得注意的是,任何未处理的私有异步任务运行()方法中发生的异常都会“冒泡”到异步事件处理程序本身。 – Jaans