您的位置:首页 > 运维架构

OPC工作记录整理——第六篇(同步读取和异步读取)

2015-01-30 21:14 477 查看
笔者博客里曾经转载过一篇关于OPC同步读取、异步读取和OPC订阅的区别的博客,其中讲的比较详细,笔者就不再过多的赘述这些内容,总之,同步读取是客户端在发出读取请求之后,需要等待服务器的响应,服务器给出回应之后,客户端才能够进行下一步的操作,而异步读取时,客户端发出请求之后,立马执行下一步的程序,当服务器给出回应之后,客户端才进行读取数据的操作。

总而言之,同步读取读取的结果直接在主程序中存入了数组中,而异步读取的结果是通过一个IOPCDataCallback的类中,有一个继承的方法叫OnReadComplete,异步读取的结果就从这个方法中返回。而这个IOPCDataCallback的类往往是用来进行OPC的数据订阅方法的读取的,所以说,数据订阅往往伴随着异步读取的方式。

下面就来看同步读取的代码。

首先是获取数据项服务句柄:

hOPCServer2[0] = (OPCHANDLE)pItemResult[0].hServer;


然后是获取同步读取指针IOPCSyncIO,注意不是IOPCAsyncIO,笔者之前就是把这个接口搞错了,所以一直没有获取到数据。根据笔者的印象,前者应该是后者的升级,好像是在OPC2.0接口中才有的。

IOPCSyncIO *pIOPCSyncIO = NULL; //第十个指针,指向同步读取
hr = pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, /*OUT*/ (void**)&pIOPCSyncIO);
if (FAILED(hr)) {
cout << "未能获取到接口IOPCSyncIO" << endl;
if (pItemResult) CoTaskMemFree(pItemResult);
if (pErrors) CoTaskMemFree(pErrors);
if (pIOPCSyncIO) CoTaskMemFree(pIOPCSyncIO);
CoTaskMemFree(&hOPCServer1);
CoTaskMemFree(&hOPCServer2);
if (pIServer) pIServer->Release();
pIServer = NULL;
if (pIUnknown) pIUnknown->Release();
pIUnknown = NULL;
if (pIEnumGUID) pIEnumGUID->Release();
pIEnumGUID = NULL;
if (pIServerList) pIServerList->Release();
pIServerList = NULL;
if (pIOPCItemMgt) pIOPCItemMgt->Release();
pIOPCItemMgt = NULL;
return 1;
}
else if (SUCCEEDED(hr)) {
ASSERT(pIOPCSyncIO);
cout << "已获取到接口IOPCSyncIO" << endl;
}
同步读取的代码:

DWORD dwItemNumber = 1;
OPCITEMSTATE *pItemValue = NULL; //第十二个指针,指向读取OPC SERVER的值

hr = pIOPCSyncIO->Read(OPC_DS_CACHE, dwItemNumber, hOPCServer2, &pItemValue, &pErrors);

if (FAILED(hr))
{
cout << "未能读取到OPC服务器端相对应的数据,请查看数据源是否有误" << endl;
if (pItemResult) CoTaskMemFree(pItemResult);
if (pErrors) CoTaskMemFree(pErrors);
if (pIOPCSyncIO) CoTaskMemFree(pIOPCSyncIO);
CoTaskMemFree(&hOPCServer1);
CoTaskMemFree(&hOPCServer2);
CoTaskMemFree(&pItemValue);
if (pIServer) pIServer->Release();
pIServer = NULL;
if (pIUnknown) pIUnknown->Release();
pIUnknown = NULL;
if (pIEnumGUID) pIEnumGUID->Release();
pIEnumGUID = NULL;
if (pIServerList) pIServerList->Release();
pIServerList = NULL;
if (pIOPCItemMgt) pIOPCItemMgt->Release();
pIOPCItemMgt = NULL;
VariantClear(&pItemValue[0].vDataValue);
return 1;   //同步读数据时出错
}
else if (SUCCEEDED(hr)){
ASSERT(hr);
cout << "已读取到OPC服务器端的数据" << endl;
cout << V_R4(&pItemValue[0].vDataValue) << endl;  //输出数据
}
异步读取其实与同步读取类似,异步读取需要获取的接口是IOPCAsyncIO2,注意不是IOPCSyncIO2,IOPCSyncIO2是IOPCAsyncIO2的升级。

hr = pIOPCItemMgt->QueryInterface(IID_IOPCAsyncIO2, /*OUT*/(void**)&pIOPCAsyncIO2); //得到第十一个指针
ASSERT(pIOPCAsyncIO2);

if (FAILED(hr)) {
cout << "未能获取到接口IOPCSyncIO2..." << endl;
if (pItemResult) CoTaskMemFree(pItemResult);
if (pErrors) CoTaskMemFree(pErrors);
CoTaskMemFree(&hOPCServer1);
CoTaskMemFree(&hOPCServer2); //第六个内存释放
CoTaskMemFree(&itemArray); //第五个内存释放
CoTaskMemFree(&clsid); //第四个内存释放
CoTaskMemFree(&catID); //第三个内存释放
CoTaskMemFree(&mqi); //第二个内存释放
CoTaskMemFree(&si); //第一个内存释放
if (pIOPCAsyncIO2) pIOPCAsyncIO2->Release(); //第十一个指针释放
pIOPCAsyncIO2 = NULL;
if (pIOPCGroupStateMgt) pIOPCGroupStateMgt->Release(); //第十个指针释放
pIOPCGroupStateMgt = NULL;
if (pIOPCItemMgt) pIOPCItemMgt->Release(); //第五个指针释放
pIOPCItemMgt = NULL;
if (pIServer) pIServer->Release(); //第四个指针释放
pIServer = NULL;
if (pIUnknown) pIUnknown->Release(); //第三个指针释放
pIUnknown = NULL;
if (pIEnumGUID) pIEnumGUID->Release(); //第二个指针释放
pIEnumGUID = NULL;
if (pIServerList) pIServerList->Release(); //第一个指针释放
pIServerList = NULL;
return 1;
}
else if (SUCCEEDED(hr)) {
cout << "已获取到接口IOPCSyncIO2..." << endl;
}
异步读取的代码:

DWORD dwItemNumber = 1;
DWORD dwCancelID;
OPCITEMSTATE *pItemValue = NULL; //第十二个指针,指向读取OPC SERVER的值

hr = pIOPCAsyncIO2->Read(dwItemNumber, hOPCServer2, 1, &dwCancelID, &pErrors); //异步读取,数据在COPCDataCallback中返回

if (FAILED(hr)) {
cout << "未能读取到OPC服务器端相对应的数据,请查看数据源是否有误..." << endl;
VariantClear(&pItemValue[0].vDataValue);
if (pItemResult) CoTaskMemFree(pItemResult);
if (pErrors) CoTaskMemFree(pErrors);
CoTaskMemFree(&hOPCServer1);
CoTaskMemFree(&hOPCServer2); //第六个内存释放
CoTaskMemFree(&itemArray); //第五个内存释放
CoTaskMemFree(&clsid); //第四个内存释放
CoTaskMemFree(&catID); //第三个内存释放
CoTaskMemFree(&mqi); //第二个内存释放
CoTaskMemFree(&si); //第一个内存释放
if (pIOPCAsyncIO2) pIOPCAsyncIO2->Release(); //第十一个指针释放
pIOPCAsyncIO2 = NULL;
if (pIOPCGroupStateMgt) pIOPCGroupStateMgt->Release(); //第十个指针释放
pIOPCGroupStateMgt = NULL;
if (pIOPCItemMgt) pIOPCItemMgt->Release(); //第五个指针释放
pIOPCItemMgt = NULL;
if (pIServer) pIServer->Release(); //第四个指针释放
pIServer = NULL;
if (pIUnknown) pIUnknown->Release(); //第三个指针释放
pIUnknown = NULL;
if (pIEnumGUID) pIEnumGUID->Release(); //第二个指针释放
pIEnumGUID = NULL;
if (pIServerList) pIServerList->Release(); //第一个指针释放
pIServerList = NULL;
return 1;   //读数据时出错
}
else if (SUCCEEDED(hr)) {
cout << "已获取到数据..." << endl;
}
异步读取的结果返回将在下一篇介绍数据订阅读取方式时再做介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: