如下实例程序:
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)来完成下面的步骤,这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了。