头盔程序员 2024-02-01 17:54 采纳率: 41.2%
浏览 8
已结题

异常System.InvalidOperationException:“线程间操作无效: 从不是创建控件“pgBar”的线程访问它 如何解决

在winform代码中通过startUpload方法开启线程,并使用委托将UploadProBar方法传递给aws对象的TestPgBar方法,然后再进行调用,但是报异常System.InvalidOperationException:“线程间操作无效: 从不是创建控件“pgBar”的线程访问它 如何解决?注:不要使用跨过线程安全检查方式解决该问题

namespace Burn
{
    public partial class Frm_File_Upload_Progress : AppListForm
    {
        public Frm_File_Upload_Progress()
        {
            InitializeComponent();
            startUpload();
        }

        private void startUpload() 
        {
            isUpload = true;
            Thread thread = new Thread(() =>
            {
                AWS aws = new AWS();
                //报错
                aws.TestPgBar(UpdateProBar);
                
            });
            thread.Start();
            thread.IsBackground = true;
        }

        private void UpdateProBar(int val)
        {
            this.pgBar.Value = val;
        }
    }
}

namespace Models
{
    public class AWS
    {
        string accessKey = "";
        string secretKey = "";
        public AmazonS3Client s3Client;
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;

        public AWS()
        {
            AmazonS3Config config = new AmazonS3Config();
            config.ServiceURL = "";
            config.ForcePathStyle = true;  //C#默认使用泛域名方式访问,修改默认配置使用url路径形式访问对象存储
            s3Client = new AmazonS3Client(
                    accessKey,
                    secretKey,
                    config
                    );
        }

        public void TestPgBar(Action<int> @updateProBar) 
        {
            for (int i = 0; i < 10; i++)
            {
                @updateProBar(i * 1000);
            }
        }
    }
}
  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-02-01 18:00
    关注

    引自免费微信小程序:皆我百晓生

    在Windows Forms应用程序中,UI控件的创建和更新必须在同一个线程上进行,这就是所谓的UI线程。当你尝试从非UI线程(如你代码中的新线程)直接修改或访问UI控件(如pgBar进度条),就会引发System.InvalidOperationException异常。

    为了解决这个问题,你需要使用Control.Invoke方法或者Action<T>MethodInvoker委托来确保对UI控件的操作是在正确的线程上下文中执行的。以下是修正后的代码:

    namespace Burn
    {
        public partial class Frm_File_Upload_Progress : AppListForm
        {
            public Frm_File_Upload_Progress()
            {
                InitializeComponent();
                startUpload();
            }
    
            private void startUpload() 
            {
                isUpload = true;
                Thread thread = new Thread(() =>
                {
                    AWS aws = new AWS();
                    aws.TestPgBar(UpdateProBarOnUIThread);
                    
                });
                thread.Start();
                thread.IsBackground = true;
            }
    
            private void UpdateProBarOnUIThread(int val)
            {
                if (this.pgBar.InvokeRequired)
                {
                    // 如果不在UI线程,则调用Invoke方法
                    this.pgBar.Invoke(new Action<int>(UpdateProBar), val);
                }
                else
                {
                    // 如果已经在UI线程,直接更新
                    this.pgBar.Value = val;
                }
            }
    
            private void UpdateProBar(int val)
            {
                // 这个方法现在只负责实际更新progressbar值
                this.pgBar.Value = val;
            }
        }
    }
    
    namespace Models
    {
        public class AWS
        {
            // ... AWS类其他部分保持不变 ...
    
            public void TestPgBar(Action<int> updateProBar) 
            {
                for (int i = 0; i < 10; i++)
                {
                    updateProBar(i * 1000);
                }
            }
        }
    }
    

    通过上述修改,当TestPgBar方法在后台线程中调用UpdateProBarOnUIThread时,会检查是否需要通过Invoke方法切换到UI线程。如果需要,则通过Invoke将更新操作封装在一个委托中,并传递给UI线程执行,从而保证了线程安全。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 2月10日
  • 已采纳回答 2月2日
  • 创建了问题 2月1日

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度