C#-WinForm跨线程修改UI界面(Task + MethodInvoker、Invoker)

说明

在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();

参考:
https://www.cnblogs.com/lsgsanxiao/p/5523282.html


原文出处:https://malaoshi.top/show_1IX6DdSb1ivd.html