说明
在Winform中,跨线程修改UI界面同样是不被允许的。在子线程中修改界面控件时Visual Studio会报出如下错误:
“System.InvalidOperationException”类型的异常在 System.Windows.Forms.dll 中发生,但未在用户代码中进行处理
其他信息: 线程间操作无效: 从不是创建控件“progressBar1”的线程访问它。
使用委托方式
控件(包括窗口)有下面两个方法实现委托:
control.invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。
control.begininvoke(参数delegate)方法:在创建控件的基础句柄所在线程上异步执行指定委托。
根据这两个概念我们大致理解invoke表是同步、begininvoke表示异步。
如果你的后台线程在更新一个UI控件的状态后不需要等待,而是要继续往下处理,那么你就应该使用BeginInvoke来进行异步处理。
如果你的后台线程需要操作UI控件,并且需要等到该操作执行完毕才能继续执行,那么你就应该使用Invoke。
方式一(推荐)
使用 Task + MethodInvoker的方式完成跨线程对UI对的修改
在按钮点击事件中加下面代码:
progressBar1.Minimum = 0;
progressBar1.Maximum = 50;
Task t = new Task(() =>
{
Console.WriteLine("任务开始工作……");
int i = progressBar1.Minimum;
for (;i <= progressBar1.Maximum; i++) {
MethodInvoker mi = new MethodInvoker(() =>
{
progressBar1.Value = i;
});
this.BeginInvoke(mi);
Thread.Sleep(100); //模拟工作过程
}
});
t.Start();
参考:
https://blog.csdn.net/baidu_37503452/article/details/106692073
方式二
在按钮点击事件中加下面代码:
progressBar1.Minimum = 0;
progressBar1.Maximum = 50;
Task t = new Task(() =>
{
Console.WriteLine("任务开始工作……");
int i = progressBar1.Minimum;
for (;i <= progressBar1.Maximum; i++) {
Invoke(new Action(() => progressBar1.Value = i));
Thread.Sleep(100); //模拟工作过程
}
});
t.Start();