没有任何工作await Task.Run()
:
private async void button2_Click(object sender, EventArgs e)
{
await Task.Run(() => {
monitor_r(label1);
});
}
protected async Task monitor_r(Label L1)
{
MessageBox.Show(L1.Name);
L1.ForeColor = Color.Blue;
L1.Text = "test";
}
这些命令
MessageBox.Show(L1.Name);
和
L1.ForeColor = Color.Blue;
工作正常,但
L1.Text = "test";
不起作用。
您能帮忙,为什么不更改Label Text
?
答案 0 :(得分:4)
尝试Control.Invoke:我们应该仅在主线程中运行Winform UI
protected async Task monitor_r(Label L1)
{
Action action = () =>
{
MessageBox.Show(L1.Name);
L1.ForeColor = Color.Blue;
L1.Text = "test";
};
if (L1.InvokeRequired)
L1.Invoke(action); // When in different thread
else
action(); // When in the main thread
}
答案 1 :(得分:1)
如果处于调试模式,请查看输出窗口。它应该显示类似这样的异常消息:
System.Windows.Forms.dll中的System.InvalidOperationException”。
那是因为label1
是从创建该线程的线程之外的线程访问的。它将导致无效的跨线程操作。
您可以通过使用Control.Invoke
来解决此问题,正如Dmitry Bychenko所述。这是对Winforms Control进行线程安全调用的简单扩展。
public static void TryInvoke(this Control control, Action<Control> action)
{
if (control.InvokeRequired) control.Invoke(new Action(() => action(control)));
else action(control);
}
示例用法
label1.TryInvoke(x => x.Text = "test");
label1.TryInvoke(x => x.ForeColor = Color.Blue);
或
this.TryInvoke(x =>
{
label1.Text = "test";
label1.ForeColor = Color.Blue;
});
第二,由于您monitor_r
不用等待任何东西,因此建议您使用void
而不是async Task
。
即使您在monitor_r
等着您,也不需要
await Task.Run(() => {
monitor_r(label1);
});
..因为monitor_r
本身是一项任务。因此,只需致电await monitor_r(label1);
答案 2 :(得分:0)
如果希望有一个单独的线程,可以使用BackgroundWorker尝试。如果有循环,可以实现ReportProgress。
echo "SELECT * FROM testtable" | mysql -h myserver -u root -pPASSWORD testdb