Control.BeginInvoke()理解之不能在非创建UI控件的线程中操作UI元素

如下实例程序:

1、声明委托类型

public delegate void valueChanged(object clientHandle, DataValue value);

2、委托实例化,并调用实例对象

 m_Subscription.AddDataMonitoredItem(nodeId, item, ClientApi_ValueChanged, 100, out serverHandle);

3、委托对象绑定的函数

private void ClientApi_ValueChanged(object clientHandle, DataValue value)

        {
            // We have to call an invoke method. 
            if (this.InvokeRequired)
            {
                // Asynchronous execution of the valueChanged delegate.
                this.BeginInvoke(new valueChanged(ClientApi_ValueChanged), clientHandle, value);
                return;
            }


            // Get the according item.
            ListViewItem item = (ListViewItem)clientHandle;


            // Set current value, status code and timestamp.
            item.SubItems[2].Text = Utils.Format("{0}", value.Value);
            item.SubItems[3].Text = Utils.Format("{0}", value.StatusCode);
            item.SubItems[4].Text = Utils.Format("{0:HH:mm:ss.fff}", value.SourceTimestamp.ToLocalTime());

        }

解析:ClientApi_ValueChanged函数中存在UI元素即ListViewItem,而委托调用该函数可能在UI线程上,也可能在非UI线程上。为了防范该冲突,通过this.InvokeRequired判断是否是非UI线程调用,若是非UI线程调用,则通过this.BeginInvoke方法将ClientApi_ValueChanged函数强制到UI线程上执行。

c#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的

当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它,此时它将会在内部调用new valueChanged(ClientApi_ValueChanged)来完成下面的步骤,这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值