OPC——(同步读取和异步读取)

  注:

1、博主地址为https://blog.csdn.net/u014801367/article/details/43309231

2、博主的opc系列文章和我们软件IOServer通过opc方式采集数据机制完全一样,可作为学习参考用

 

 

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

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

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

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

 

[cpp]  view plain  copy
 
  1. hOPCServer2[0] = (OPCHANDLE)pItemResult[0].hServer;  


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

 

 

[cpp]  view plain  copy
 
  1. IOPCSyncIO *pIOPCSyncIO = NULL; //第十个指针,指向同步读取  
  2. hr = pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, /*OUT*/ (void**)&pIOPCSyncIO);  
  3. if (FAILED(hr)) {  
  4.     cout << "未能获取到接口IOPCSyncIO" << endl;  
  5.     if (pItemResult) CoTaskMemFree(pItemResult);  
  6.     if (pErrors) CoTaskMemFree(pErrors);  
  7.     if (pIOPCSyncIO) CoTaskMemFree(pIOPCSyncIO);  
  8.     CoTaskMemFree(&hOPCServer1);  
  9.     CoTaskMemFree(&hOPCServer2);  
  10.     if (pIServer) pIServer->Release();  
  11.     pIServer = NULL;  
  12.     if (pIUnknown) pIUnknown->Release();  
  13.     pIUnknown = NULL;  
  14.     if (pIEnumGUID) pIEnumGUID->Release();  
  15.     pIEnumGUID = NULL;  
  16.     if (pIServerList) pIServerList->Release();  
  17.     pIServerList = NULL;  
  18.     if (pIOPCItemMgt) pIOPCItemMgt->Release();  
  19.     pIOPCItemMgt = NULL;  
  20.     return 1;  
  21. }  
  22. else if (SUCCEEDED(hr)) {  
  23.     ASSERT(pIOPCSyncIO);  
  24.     cout << "已获取到接口IOPCSyncIO" << endl;  
  25. }  

同步读取的代码:

 

 

[cpp]  view plain  copy
 
  1. DWORD dwItemNumber = 1;  
  2. OPCITEMSTATE *pItemValue = NULL; //第十二个指针,指向读取OPC SERVER的值  
  3.   
  4. hr = pIOPCSyncIO->Read(OPC_DS_CACHE, dwItemNumber, hOPCServer2, &pItemValue, &pErrors);  
  5.   
  6. if (FAILED(hr))  
  7. {  
  8.     cout << "未能读取到OPC服务器端相对应的数据,请查看数据源是否有误" << endl;  
  9.     if (pItemResult) CoTaskMemFree(pItemResult);  
  10.     if (pErrors) CoTaskMemFree(pErrors);  
  11.     if (pIOPCSyncIO) CoTaskMemFree(pIOPCSyncIO);  
  12.     CoTaskMemFree(&hOPCServer1);  
  13.     CoTaskMemFree(&hOPCServer2);  
  14.     CoTaskMemFree(&pItemValue);  
  15.     if (pIServer) pIServer->Release();  
  16.     pIServer = NULL;  
  17.     if (pIUnknown) pIUnknown->Release();  
  18.     pIUnknown = NULL;  
  19.     if (pIEnumGUID) pIEnumGUID->Release();  
  20.     pIEnumGUID = NULL;  
  21.     if (pIServerList) pIServerList->Release();  
  22.     pIServerList = NULL;  
  23.     if (pIOPCItemMgt) pIOPCItemMgt->Release();  
  24.     pIOPCItemMgt = NULL;  
  25.     VariantClear(&pItemValue[0].vDataValue);  
  26.     return 1;   //同步读数据时出错  
  27. }  
  28. else if (SUCCEEDED(hr)){  
  29.         ASSERT(hr);  
  30.     cout << "已读取到OPC服务器端的数据" << endl;  
  31.     cout << V_R4(&pItemValue[0].vDataValue) << endl;  //输出数据  
  32. }  

    异步读取其实与同步读取类似,异步读取需要获取的接口是IOPCAsyncIO2,注意不是IOPCSyncIO2,IOPCSyncIO2是IOPCAsyncIO2的升级。

 

 

[cpp]  view plain  copy
 
  1. hr = pIOPCItemMgt->QueryInterface(IID_IOPCAsyncIO2, /*OUT*/(void**)&pIOPCAsyncIO2); //得到第十一个指针  
  2. ASSERT(pIOPCAsyncIO2);  
  3.   
  4. if (FAILED(hr)) {  
  5.     cout << "未能获取到接口IOPCSyncIO2..." << endl;  
  6.     if (pItemResult) CoTaskMemFree(pItemResult);  
  7.     if (pErrors) CoTaskMemFree(pErrors);  
  8.     CoTaskMemFree(&hOPCServer1);  
  9.     CoTaskMemFree(&hOPCServer2); //第六个内存释放  
  10.     CoTaskMemFree(&itemArray); //第五个内存释放  
  11.     CoTaskMemFree(&clsid); //第四个内存释放  
  12.     CoTaskMemFree(&catID); //第三个内存释放  
  13.     CoTaskMemFree(&mqi); //第二个内存释放  
  14.     CoTaskMemFree(&si); //第一个内存释放  
  15.     if (pIOPCAsyncIO2) pIOPCAsyncIO2->Release(); //第十一个指针释放  
  16.     pIOPCAsyncIO2 = NULL;  
  17.     if (pIOPCGroupStateMgt) pIOPCGroupStateMgt->Release(); //第十个指针释放  
  18.     pIOPCGroupStateMgt = NULL;  
  19.     if (pIOPCItemMgt) pIOPCItemMgt->Release(); //第五个指针释放  
  20.     pIOPCItemMgt = NULL;  
  21.     if (pIServer) pIServer->Release(); //第四个指针释放  
  22.     pIServer = NULL;  
  23.     if (pIUnknown) pIUnknown->Release(); //第三个指针释放  
  24.     pIUnknown = NULL;  
  25.     if (pIEnumGUID) pIEnumGUID->Release(); //第二个指针释放  
  26.     pIEnumGUID = NULL;  
  27.     if (pIServerList) pIServerList->Release(); //第一个指针释放  
  28.     pIServerList = NULL;  
  29.     return 1;  
  30. }  
  31. else if (SUCCEEDED(hr)) {         
  32.     cout << "已获取到接口IOPCSyncIO2..." << endl;  
  33. }  

    异步读取的代码:

 

 

[cpp]  view plain  copy
 
  1. DWORD dwItemNumber = 1;  
  2. DWORD dwCancelID;  
  3. OPCITEMSTATE *pItemValue = NULL; //第十二个指针,指向读取OPC SERVER的值  
  4.   
  5. hr = pIOPCAsyncIO2->Read(dwItemNumber, hOPCServer2, 1, &dwCancelID, &pErrors); //异步读取,数据在COPCDataCallback中返回  
  6.   
  7. if (FAILED(hr)) {  
  8.     cout << "未能读取到OPC服务器端相对应的数据,请查看数据源是否有误..." << endl;  
  9.     VariantClear(&pItemValue[0].vDataValue);  
  10.     if (pItemResult) CoTaskMemFree(pItemResult);  
  11.     if (pErrors) CoTaskMemFree(pErrors);  
  12.     CoTaskMemFree(&hOPCServer1);  
  13.     CoTaskMemFree(&hOPCServer2); //第六个内存释放  
  14.     CoTaskMemFree(&itemArray); //第五个内存释放  
  15.     CoTaskMemFree(&clsid); //第四个内存释放  
  16.     CoTaskMemFree(&catID); //第三个内存释放  
  17.     CoTaskMemFree(&mqi); //第二个内存释放  
  18.     CoTaskMemFree(&si); //第一个内存释放  
  19.     if (pIOPCAsyncIO2) pIOPCAsyncIO2->Release(); //第十一个指针释放  
  20.     pIOPCAsyncIO2 = NULL;  
  21.     if (pIOPCGroupStateMgt) pIOPCGroupStateMgt->Release(); //第十个指针释放  
  22.     pIOPCGroupStateMgt = NULL;  
  23.     if (pIOPCItemMgt) pIOPCItemMgt->Release(); //第五个指针释放  
  24.     pIOPCItemMgt = NULL;  
  25.     if (pIServer) pIServer->Release(); //第四个指针释放  
  26.     pIServer = NULL;  
  27.     if (pIUnknown) pIUnknown->Release(); //第三个指针释放  
  28.     pIUnknown = NULL;  
  29.     if (pIEnumGUID) pIEnumGUID->Release(); //第二个指针释放  
  30.     pIEnumGUID = NULL;  
  31.     if (pIServerList) pIServerList->Release(); //第一个指针释放  
  32.     pIServerList = NULL;  
  33.     return 1;   //读数据时出错  
  34. }  
  35. else if (SUCCEEDED(hr)) {  
  36.     cout << "已获取到数据..." << endl;  
  37. }  

    异步读取的结果返回将在下一篇介绍数据订阅读取方式时再做介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值