open62541中使用UA_Client_MonitoredItems_createDataChanges批量创建监控项后回调不触发问题求助
open62541中使用UA_Client_MonitoredItems_createDataChanges批量创建监控项后回调不触发问题求助
各位open62541的大佬们,我最近在用open62541 v1.x开发OPC UA客户端时,遇到了批量创建监控项的回调不触发的诡异问题——单条创建标签一切正常,换成批量API后,监控项明明创建成功了,但回调函数死活不执行,实在卡壳了,来求助大家!
背景
我需要批量订阅大量OPC UA标签,单条调用UA_Client_MonitoredItems_createDataChange()完全没问题,但为了性能考虑换成批量API后就出问题了。
✅ 正常工作的单条创建实现
先贴一下单条创建的核心代码,这部分是完全正常的:
UA_MonitoredItemCreateResult monResponse = UA_Client_MonitoredItems_createDataChange( client, subscriptionId, UA_TIMESTAMPSTORETURN_BOTH, monRequest, monContext, handler_DataChange, nullptr);
对应的现象:
- 所有监控项都能成功创建
- 回调函数
handler_DataChange被正确调用 - 标签值能正常接收
❌ 不工作的批量创建实现
换成批量APIUA_Client_MonitoredItems_createDataChanges()后,监控项创建成功,但回调完全不触发。以下是核心实现代码:
UA_CreateMonitoredItemsRequest req; UA_CreateMonitoredItemsRequest_init(&req); req.subscriptionId = subscriptionId; req.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH; req.itemsToCreateSize = tags.size(); req.itemsToCreate = (UA_MonitoredItemCreateRequest*)UA_Array_new( tags.size(), &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST]); // 用全局容器持久化存储上下文和回调,避免超出作用域被销毁 auto& ctxList = subscriptionContexts[subscriptionId]; auto& cbList = subscriptionCallbacks[subscriptionId]; for (size_t i = 0; i < tags.size(); i++) { UA_MonitoredItemCreateRequest_init(&req.itemsToCreate[i]); UA_NodeId nodeId = parseNodeIdFromAddress(tags[i]->address, logger); UA_NodeId_copy(&nodeId, &req.itemsToCreate[i].itemToMonitor.nodeId); req.itemsToCreate[i].itemToMonitor.attributeId = UA_ATTRIBUTEID_VALUE; // 存储上下文到持久化列表 auto ctx = std::make_unique<MonContext>(); ctx->deviceId = device->uniqueId; ctx->tag = tags[i]; ctxList.push_back(std::move(ctx)); // 存储回调函数到持久化列表 cbList.push_back(handler_DataChange); UA_NodeId_clear(&nodeId); } // 转换为批量API需要的原始指针数组 std::vector<void*> ctxRaw; for (auto& c : ctxList) ctxRaw.push_back(c.get()); std::vector<UA_Client_DataChangeNotificationCallback> cbRaw; for (auto& cb : cbList) cbRaw.push_back(cb); // 调用批量创建API UA_CreateMonitoredItemsResponse resp = UA_Client_MonitoredItems_createDataChanges( client, req, ctxRaw.data(), cbRaw.data(), nullptr);
对应的现象:
- ✅ 服务器返回
UA_STATUSCODE_GOOD,所有监控项创建成功 - ✅ 每个项都拿到了正确的
MonitoredItemId - ❌ 所有分配的回调函数
handler_DataChange从未被触发 - ❌ 客户端能收到服务器的Publish响应,但响应里的通知数量为0
我已经排查过的点
- 回调和上下文的生命周期:用全局容器持久化存储了
ctxList和cbList,绝对没有超出作用域被销毁 - 回调函数本身:同一个
handler_DataChange在单条模式下完全正常工作 - 服务器状态:服务器能正常发布标签值(单条订阅可以收到)
- 订阅参数:采样间隔、队列大小等参数和单条模式完全一致,都是正确的
- 返回结果校验:创建请求的响应里,所有项的状态码都是
UA_STATUSCODE_GOOD
我的疑问
为什么批量API能成功创建监控项,但完全不触发回调?单条模式下同一个回调明明是正常的。
关于批量API的上下文和回调数组,有没有什么特殊的结构要求?比如存储顺序、格式?或者open62541 v1.x在批量创建监控项上有已知的限制或bug吗?
折腾了好几天都没找到问题所在,求各位大佬指点迷津!🙏




