博客

  • 密码保护:个人心事

    密码保护:个人心事

    此内容受密码保护。如需查阅,请在下方输入密码。

  • [C#笔记] 解决 WinForm 跨线程更新 UI 报错的问题

    最近在写一个小工具的时候踩了个坑,记录一下以防下次忘记。

    问题描述: 我在后台开了一个 Task 去处理一些耗时的数据,处理完后想把结果显示在界面的 TextBox 里。结果一运行程序就直接崩了,抛出了一个经典的异常:

    System.InvalidOperationException: 'Cross-thread operation not valid: Control 'textBoxLog' accessed from a thread other than the thread it was created on.'

    也就是常说的“线程间操作无效”。因为 WinForm 的 UI 控件并不是线程安全的,子线程不能直接去动主线程创建的控件。

    // 模拟后台任务
    Task.Run(() => 
    {
        Thread.Sleep(1000); // 假装在工作
        
        // 直接操作 UI 控件 -> 报错!
        this.textBoxLog.AppendText("任务完成!"); 
    });

    解决方法: 其实很简单,判断一下 InvokeRequired,然后用 this.Invoke 把操作封送回主线程就行了。

    Task.Run(() => 
    {
        Thread.Sleep(1000);
    
        // 检查是否需要跨线程调用
        if (this.textBoxLog.InvokeRequired)
        {
            // 使用 Invoke 委托给主线程执行
            this.textBoxLog.Invoke(new Action(() => 
            {
                this.textBoxLog.AppendText("任务完成!\r\n");
            }));
        }
        else
        {
            this.textBoxLog.AppendText("任务完成!");
        }
    });

    搞定,程序不再崩溃了。虽然 WPF 有 Dispatcher,但 WinForm 这一套 Invoke 还是得熟练掌握才行。