c# 多线程运行时出现主界面卡死现象如何解决?

2025-04-06 16:58:41
推荐回答(2个)
回答1:

无论是哪种语言都一样,控件是主线程在运行的,你创建新的线程去跨线程访问就会冲突,在一个线程里处理一个事情,另一个线程被忽略,肯定会假死。举个例子,用C#,我拖放一个richtextbox记录事件,一个button触发事件开始,一个label记录进度,一个progressBar显示进度。

        //线程工作
        private void even()
        {
            invor("准备就绪\r\n", 0, eventpe.sta);
            Thread.Sleep(500);
            invor("通道1数据采集完毕......." + DateTime.UtcNow.ToLocalTime().ToLongTimeString() + "\r\n", 20,eventpe.doev);
            Thread.Sleep(2000);
            invor("通道2数据采集完毕......." + DateTime.UtcNow.ToLocalTime().ToLongTimeString() + "\r\n", 40, eventpe.doev);
            Thread.Sleep(3000);
            invor("通道3数据采集完毕......." + DateTime.UtcNow.ToLocalTime().ToLongTimeString() + "\r\n", 70, eventpe.doev);
            Thread.Sleep(500);
            invor("通道4数据请求失败......." + DateTime.UtcNow.ToLocalTime().ToLongTimeString() + "\r\n", 75, eventpe.doev);
            Thread.Sleep(2000);
            invor("通道5数据采集完毕......." + DateTime.UtcNow.ToLocalTime().ToLongTimeString() + "\r\n", 95, eventpe.doev);
            Thread.Sleep(2000);
            invor("数据比对分析中...\r\n", 98, eventpe.doev);
            Thread.Sleep(500);
            invor("Done!", 100, eventpe.end);

        }
        //枚举线程状态
        enum eventpe
        {
            sta,doev,end
        }
        //委托主线程控件方法
        void invor(string sg,int va,eventpe ik)
        {
            switch(ik)
            {
                case eventpe.sta:
                    richTextBox1.BeginInvoke(new EventHandler(delegate {
                        richTextBox1.Text = sg;
                    }));
                    progressBar1.BeginInvoke(new EventHandler(delegate {
                        progressBar1.Visible = true;
                        progressBar1.Value = 0;
                    }));
                    label1.BeginInvoke(new EventHandler(delegate {
                        label1.Visible = true;
                        label1.Text = "0%";
                    }));
                    break;
                case eventpe.doev:
                    progressBar1.BeginInvoke(new EventHandler(delegate {
                        progressBar1.Value = va;
                    }));
                    label1.BeginInvoke(new EventHandler(delegate {
                        label1.Text = va.ToString() + "%";
                    }));
                    richTextBox1.BeginInvoke(new EventHandler(delegate {
                        richTextBox1.Text += sg;
                    }));
                    break;
                case eventpe.end:
                    progressBar1.BeginInvoke(new EventHandler(delegate {
                        progressBar1.Visible =false;
                    }));
                    label1.BeginInvoke(new EventHandler(delegate {
                        label1.Visible =false;
                    }));
                    break;
            }
        }
        //初始化按钮事件和状态
        public void btn_event()
        {
            //初始化
            progressBar1.Visible = false;
            label1.Visible = false;
            //按钮事件
            btn.Click += (object sen, EventArgs ed) =>
              {
                  Thread.Sleep(500);
                  Thread th = new Thread(even);
                  th.Start();
              };
        }

在程序中直接加入初始化就好了

        public Form1()
        {
            InitializeComponent();
            btn_event();
        }

这就是一个真正的多线程

回答2:

我建议你用BackgroundWorker控件比较好,简单易用,我做多线程的时候就常用这个~