OPC UA客户端无法接收服务器删除MonitoredItem的通知,求客户端侧解决方案
解决OPC UA客户端接收服务器删除监控项通知的问题
在OPC UA协议中,当服务器端删除监控项对应的节点时,MonitoredItem的Notification事件不会主动触发删除通知,但可以通过监听订阅状态变化和检查监控项状态码两种客户端侧方案实现需求:
方案1:监听Subscription的StatusChanged事件
订阅(Subscription)的状态变化事件会捕获监控项的异常状态,遍历订阅内的监控项即可识别被删除的节点:
代码实现
// 初始化订阅时绑定状态变化事件 Subscription subscription = new Subscription(session, PublishingInterval: 1000); subscription.StatusChanged += Subscription_StatusChanged; // 将你的监控项添加到订阅并启动 subscription.AddItem(monItem); session.AddSubscription(subscription); subscription.Create(); // 订阅状态变化处理方法 private void Subscription_StatusChanged(Subscription sender, StatusChangeEventArgs e) { foreach (var monitoredItem in sender.MonitoredItems.ToList()) // 使用ToList避免遍历中修改集合 { var statusCode = monitoredItem.StatusCode.StatusCode; // 匹配节点被删除或节点ID无效的状态码 if (statusCode == StatusCodes.BadNodeIdUnknown || statusCode == StatusCodes.BadNodeDeleted) { // 执行自定义删除通知逻辑 HandleMonitoredItemDeleted(monitoredItem); // 从订阅中移除失效的监控项 sender.RemoveItem(monitoredItem); } } } // 自定义处理监控项删除的业务逻辑 private void HandleMonitoredItemDeleted(MonitoredItem item) { Console.WriteLine($"监控项 [{item.DisplayName}] (NodeId: {item.StartNodeId}) 已被服务器删除"); // 这里添加你的业务操作:更新UI、记录日志、清理资源等 }
方案2:在MonitoredItem的Notification事件中检查状态码
如果服务器在节点删除后仍会推送一次错误状态的数据,可以在值更新事件中直接检查状态码:
代码实现
private void MonItem_Notification(MonitoredItem sender, MonitoredItemNotificationEventArgs e) { foreach (var notification in e.Notifications) { if (notification is DataValueNotification dataValueNotify) { var statusCode = dataValueNotify.Value.StatusCode.StatusCode; if (statusCode == StatusCodes.BadNodeIdUnknown || statusCode == StatusCodes.BadNodeDeleted) { HandleMonitoredItemDeleted(sender); return; } // 正常处理值更新逻辑 Console.WriteLine($"收到值更新: {dataValueNotify.Value.Value}"); } } }
注意事项
- 依赖订阅的
PublishingInterval参数,间隔越小状态通知越及时,但会增加网络开销 - 方案1更可靠,因为部分服务器删除节点后不会触发
Notification事件,只会更新监控项状态 - 处理时使用
ToList()遍历监控项,避免在遍历过程中修改集合引发异常
内容的提问来源于stack exchange,提问作者The Kingmaker
相关产品推荐
相关产品推荐

