我过去使用过代理来更新当前的UI(例如文本框),其中包含在我的线程中处理的值.我是在假设async并await为你照顾这个.
当我运行下面的代码时 - 按下按钮时,启动一个新的任务,每100ms计数100次.计数应显示在UI上,但我得到一个targetInvocationException:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = "Press button";
}
private async void button1_Click(object sender, EventArgs e)
{
await Task1();
}
private Task Task1()
{
return Task.Factory.StartNew(() => CountMethod());
}
private void CountMethod()
{
for (int i = 0; i < 100; i++)
{
Task.Delay(100).Wait();
//Console.WriteLine(i.ToString());
textBox1.Text = i.ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是您正在使用线程池线程来访问UI.您正在使用该Task.Factory.StartNew方法执行此操作.
以下是如何解决它:
private async Task Task1()
{
for (int i = 0; i < 100; i++)
{
await Task.Delay(100);
textBox1.Text = i.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
await将捕获当前,SynchronizationContext以便在异步等待完成后,后续代码在UI线程上执行.这是真的,因为awaitUI线程调用了(在我的例子中).
在当前代码中,await在线程池线程上调用.在这种情况下,当前SynchronizationContext为空,因此异步等待之后的代码也将在线程池线程上执行.