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

    笔者博客里曾经转载过一篇关于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;
}
    异步读取的结果返回将在下一篇介绍数据订阅读取方式时再做介绍。



评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值