c#中使用多线程访问winform中控件

来源:互联网 发布:得到网站源码有什么用 编辑:程序博客网 时间:2024/04/28 08:33

我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。

      首先来看传统方法:

      public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(ThreadFuntion);
            thread.IsBackground = true;
            thread.Start();
        }
        private void ThreadFuntion()
        {
            while (true)
            {
                this.textBox1.Text = DateTime.Now.ToString();
                Thread.Sleep(1000);
            }
        }
    }

       运行这段代码,我们会看到系统抛出一个异常:Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on . 这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。那么怎么解决这个问题呢,下面提供几种方案。

      第一种方案,我们在Form1_Load()方法中加一句代码:

      private void Form1_Load(object sender, EventArgs e)
      {
            Control.CheckForIllegalCrossThreadCalls = false;
            Thread thread = new Thread(ThreadFuntion);
            thread.IsBackground = true;
            thread.Start();
        }
      加入这句代码以后发现程序可以正常运行了。这句代码就是说在这个类中我们不检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。然而,这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。

      下面来看第二种方案,就是使用delegate和invoke来从其他线程中控制控件信息。网上有很多人写了这种控制方式,然而我看了很多这种帖子,表明上看来是没有什么问题的,但是实际上并没有解决这个问题,首先来看网络上的那种不完善的方式:

public partial class Form1 : Form
    {
        private delegate void FlushClient();//代理
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(CrossThreadFlush);

            thread.IsBackground=true;
            thread.Start();
        }

        private void CrossThreadFlush()
        {
            //将代理绑定到方法 
            FlushClient fc = new FlushClient(ThreadFuntion);
            this.BeginInvoke(fc);//调用代理
        }
        private void ThreadFuntion()
        {
            while (true)
            {
                this.textBox1.Text = DateTime.Now.ToString();
                Thread.Sleep(1000);
            }
        }
    }

       使用这种方式我们可以看到跨线程访问的异常没有了。但是新问题出现了,界面没有响应了。为什么会出现这个问题,我们只是让新开的线程无限循环刷新,理论上应该不会对主线程产生影响的。


其实不然,这种方式其实相当于把这个新开的线程“注入”到了主控制线程中,它取得了主线程的控制。只要这个线程不返回,那么主线程将永远都无法响应。就算新开的线程中不使用无限循环,使可以返回了。这种方式的使用多线程也失去了它本来的意义。

       现在来让我们看看推荐的解决方案:

public partial class Form1 : Form
    {
        private delegate void FlushClient();//代理
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(CrossThreadFlush);
            thread.IsBackground = true;
            thread.Start();
        }

        private void CrossThreadFlush()
        {
            while (true)
            {
                //将sleep和无限循环放在等待异步的外面
                Thread.Sleep(1000);
                ThreadFunction();
            }
        }
        private void ThreadFunction()
        {
            if (this.textBox1.InvokeRequired)//等待异步
            {
                FlushClient fc = new FlushClient(ThreadFunction);
                this.Invoke(fc);//通过代理调用刷新方法
            }
            else
            {
                this.textBox1.Text = DateTime.Now.ToString();
            }
        }
    }

       运行上述代码,我们可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform多线程控件的控制了

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米不小心把手机联系人删了怎么办 58同城小区名输不了怎么办 e路发注册直接有积分怎么办 大众速腾的不锈钢圈被碰花了怎么办 公司卡着生育险不给怎么办 济南图书馆借书超过期限了怎么办 淘宝解绑支付宝支付密码不对怎么办 微博支付宝支付密码忘记了怎么办 图虫签约师通过了认证标识怎么办 签证做假工作证明资料被拒怎么办 在广州办个建设厅电工证怎么办 水利考的五大员证到有效期怎么办 额头注射玻尿酸吸收后不平怎么办 施工员证书挂靠拿不回来怎么办 森林公安未转政法编制的人员怎么办 北京的限行新政策外地车怎么办 报考二级建造师工作年限不够怎么办 郑州航院图书馆密码忘了怎么办 无锡妇幼预约挂号过号了怎么办 云南建筑八大员考试没通过怎么办 订车ax7一个月提不到车怎么办 提车时间到了却没车怎么办 一汽大众速腾气囊灯亮该怎么办呢? 幼儿园上课时候电脑上的课件怎么办 黑米紫薯红豆粥不好煮怎么办 母狗生了小狗后不吃东西没奶怎么办 狗给扑倒了主人不想负责怎么办 山东政务网个人中心账号忘了怎么办 网易博客忘记登入名和密码了怎么办 奶水不够怎么办怎样让奶水变多 和初恋分手多年又爱上初恋该怎么办 分手六年的初恋想要和我复合怎么办 不小心把手机里的视频删了怎么办 网签过了中介不配合过户怎么办 房屋被中介恶意网签了怎么办 重介质选矿块矿品位低怎么办 去泰国酒吧选小姐只会说中文怎么办 脚被窝烫伤后发炎里面有龙怎么办 脚被窝烫了发炎有龙怎么办 辣椒落花的药喷到孩子嘴巴了怎么办 香炉里的小米生虫子了怎么办