跨线程更新界面(winform下 C#)

.net 不允许跨线程访问控件

会提示 不是由创建线程访问

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

解决方案:

1、设置Control.CheckForIllegalCrossThreadCalls

        2、在工作线程使用委托

使用Control.BeginInvoke/Invoke 

说明: 

1、实际Control调用 begininvoke/invoke不会创建新线程 实际相当于post/send message

两者区别:

PostMessage只负责将消息放到消息队列中,不确定何时及是否处理
    SendMessage要等到受到消息处理的返回码(DWord类型)后才继续
    PostMessage执行后马上返回
    SendMessage必须等到消息被处理后才会返回。
       2. invoke 执行的委托 实际在由主线程执行函数

对比下面两个方式

#region 跨线程调用方法测试
        delegate void newDelegate();
        public void thMethod() 
        {
            //方案一
            //newDelegate del = new newDelegate(changeUI);
            //this.BeginInvoke(del);
            ///*方案二
            while (true) 
            {
                Thread.Sleep(1000);
                changeUI();
            }
            //*/

        }
        public void changeUI()
        {
            /*//方案一
            while (true)
            {
                Thread.Sleep(1000);
                this.label1.Text = System.DateTime.Now.ToString();
            }*/
            ///*方案二
            if (label1.InvokeRequired)
            {
                newDelegate de = new newDelegate(changeUI);
                this.BeginInvoke(de);
            }
            else
                this.label1.Text = System.DateTime.Now.ToString();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(thMethod);
            th.IsBackground = true;
            th.Start();
        }
        #endregion


changeUI函数委托在主线执行

方案一 在changeUI中执行了 死循环 会让主线程卡死

方案二 在thMethod中由工作线程执行死循环 不会影响主线程更新控件的工作


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WinForm程序中,UI界面是由主线程(也称UI线程)负责更新的,其他线程不能直接修改UI界面数据,否则会抛出异常。如果需要线程更新UI界面数据,可以使用以下几种方法: 1. 使用Control.Invoke方法:该方法可以将UI线程委托一个方法来执行,从而实现线程更新UI界面数据。例如: ``` private void UpdateUI(string data) { if (this.InvokeRequired) { this.Invoke(new Action<string>(UpdateUI), data); } else { label1.Text = data; } } ``` 2. 使用Control.BeginInvoke方法:该方法与Invoke类似,但是它是异步的。它会立即返回,而不是等待委托方法执行完毕。例如: ``` private void UpdateUI(string data) { if (this.InvokeRequired) { this.BeginInvoke(new Action<string>(UpdateUI), data); } else { label1.Text = data; } } ``` 3. 使用SynchronizationContext类:该类可以在不同线程之间传递上下文信息,从而实现线程更新UI界面数据。例如: ``` private SynchronizationContext _syncContext; public Form1() { InitializeComponent(); _syncContext = SynchronizationContext.Current; } private void UpdateUI(string data) { _syncContext.Post(new SendOrPostCallback((obj) => { label1.Text = obj.ToString(); }), data); } ``` 以上三种方法都可以实现线程更新UI界面数据,根据实际情况和个人习惯选择即可。需要注意的是,线程更新UI界面数据是一个比较耗时的操作,如果频繁调用会对程序的性能产生影响。因此,建议仅在必要时使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值