一直用C++操作opc搞工控十多年了,从来都是同步读写,因为时效性并不要求过高,所以秉承“够用就行”的原则。其次也是因为同步读对异常处理比较方便。近来研究异步读写时,发现读取的数值与同步读取数值完全不一样,似乎顺序是乱的。
待认真研究代码后才发现,同步和异步的读取还是有本质区别的,不仅仅是异步回调的区别。
同步读取函数:
virtual HRESULT STDMETHODCALLTYPE Read(
/* [in] */ OPCDATASOURCE dwSource,
/* [in] */ DWORD dwCount,
/* [size_is][in] */ OPCHANDLE *phServer,
/* [size_is][size_is][out] */ OPCITEMSTATE **ppItemValues,
/* [size_is][size_is][out] */ HRESULT **ppErrors) = 0;
ppItemValues(实时值)数组的顺序就是引入变量时的顺序。
而异步读取回调函数:
STDMETHODIMP COPCDataCallback::OnReadComplete(
/* [in] */ DWORD dwTransid,
/* [in] */ OPCHANDLE hGroup,
/* [in] */ HRESULT hrMasterquality,
/* [in] */ HRESULT hrMastererror,
/* [in] */ DWORD dwCount,
/* [size_is][in] */ OPCHANDLE __RPC_FAR *phClientItems, //异步读的Items顺序与同步不一样,重新调整了
/* [size_is][in] */ VARIANT __RPC_FAR *pvValues,
/* [size_is][in] */ WORD __RPC_FAR *pwQualities,
/* [size_is][in] */ FILETIME __RPC_FAR *pftTimeStamps,
/* [size_is][in] */ HRESULT __RPC_FAR *pErrors)
pvValues(实时值)数组的顺序并不是引入时的变量顺序,其顺序对应的是变量顺序数组phClientItems。
因此需要做一个顺序转换才能一一对应:
if (pErrors[0] == S_OK)
{
DWORD i;
for (i = 0; i < dwCount; i++)
{
int x= phClientItems[i]-1; //变量顺序号
readValue[x] = pvValues[i].uiVal ;
readQulity[x] = GetQualityText(pwQualities[i]);
char pstrDateTime[32]={0};
FileTimeToLocalSystemTime(pftTimeStamps[i], pstrDateTime);
readTS[x] = pstrDateTime;
}
}