/// <summary>Reads opc-items via an synchronous read</summary> /// <param name="OPCDataSrc">determines the source, the data have to be read (cache or device)</param> /// <param name="itemServerHandles">the serverhandles of the opc-items to be read</param> /// <param name="theGroup">the group in which the opc-items are hosted</param> /// <returns> itemstates, returned form the opc-server </returns> public OPCITEMSTATE[] readSync(OpcRcw.Da.OPCDATASOURCE OPCDataSrc, int[] itemServerHandles, out int[] errors) { if (m_disposed) { throw new NullReferenceException("This object has been disposed!"); } IntPtr pItemStates = IntPtr.Zero; IntPtr pErrors = IntPtr.Zero; int NumItems = itemServerHandles.Length; OPCITEMSTATE[] result = new OPCITEMSTATE[NumItems]; string ErrorStr = ""; try { // Usually reading from CACHE is more efficient // AND the underlying device has to do less communication work. // BUT, you must have an active ITEM and GROUP, so that the opc server // will update the data by itself; otherwise you'll get quality OUT_OF_SERVICE m_OPCSyncIO.Read(OPCDataSrc, //OPCDATASOURCE.OPC_DS_DEVICE or OPCDATASOURCE.OPC_DS_CACHE, NumItems, itemServerHandles, out pItemStates, out pErrors); if (pItemStates == IntPtr.Zero) { throw new ArgumentNullException("EXT_OPC_RDSYNC_ITEMSTATES"); } if (pErrors == IntPtr.Zero) { throw new ArgumentNullException("EXT_OPC_RDSYNC_ERRORS"); } //Evaluate return ErrorCodes to exclude possible Errors errors = new int[NumItems]; Marshal.Copy(pErrors, errors, 0, NumItems); IntPtr pos = pItemStates; // Now get the read values and check errors for (int dwCount = 0; dwCount < NumItems; dwCount++) { result[dwCount] = (OPCITEMSTATE)Marshal.PtrToStructure(pos, typeof(OPCITEMSTATE)); if (errors[dwCount] != 0) { m_OPCServer.GetErrorString(errors[dwCount], m_LocaleID, out ErrorStr); System.Diagnostics.Debug.WriteLine(ErrorStr); } pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMSTATE))); } if (ErrorStr != "") { throw new Exception(ErrorStr); } // Free allocated COM-ressouces Marshal.FreeCoTaskMem(pItemStates); Marshal.FreeCoTaskMem(pErrors); } catch (Exception) { // Free allocated COM-ressouces Marshal.FreeCoTaskMem(pItemStates); Marshal.FreeCoTaskMem(pErrors); // just forward it throw; } return(result); }
/*------------------------------------------------------ * Execute SyncRead * * (ret) True OK * False NG * ------------------------------------------------------*/ public bool SyncRead(OpcRcw.Da.OPCDATASOURCE DataSource, int[] ServerHd, object[] Values, OpcRcw.Da.FILETIME[] TimeStamps, short[] Qualities) { int iItemCount = ServerHd.Length; IOPCSyncIO OPCSyncIO; IOPCSyncIO2 OPCSyncIO2; IntPtr ppItemVal; IntPtr ppErrors; IntPtr posItem; int[] Errors = new int[iItemCount]; OPCITEMSTATE ItemState; int i; try { switch (m_OpcdaVer) { case DEF_OPCDA.VER_30: OPCSyncIO2 = (IOPCSyncIO2)m_OPCGroup2; OPCSyncIO2.Read(DataSource, iItemCount, ServerHd, out ppItemVal, out ppErrors); Marshal.Copy(ppErrors, Errors, 0, iItemCount); posItem = ppItemVal; for (i = 0; i < iItemCount; i++) { ItemState = (OPCITEMSTATE)Marshal.PtrToStructure(posItem, typeof(OPCITEMSTATE)); if (Errors[i] == 0) { Values[i] = ItemState.vDataValue; TimeStamps[i] = ItemState.ftTimeStamp; Qualities[i] = ItemState.wQuality; } Marshal.DestroyStructure(posItem, typeof(OPCITEMSTATE)); // 05/02/08 Release memory //posItem = new IntPtr(posItem.ToInt32() + Marshal.SizeOf(typeof(OPCITEMSTATE))); // 1.0.0.5 10/06/21 Kishimoto Fixed for Memory Leak posItem = (IntPtr)(posItem.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); // 1.0.0.5 10/06/21 Kishimoto Fixed for Memory Leak } Marshal.FreeCoTaskMem(ppItemVal); Marshal.FreeCoTaskMem(ppErrors); break; case DEF_OPCDA.VER_10: case DEF_OPCDA.VER_20: default: OPCSyncIO = (IOPCSyncIO)m_OPCGroup; OPCSyncIO.Read(DataSource, iItemCount, ServerHd, out ppItemVal, out ppErrors); Marshal.Copy(ppErrors, Errors, 0, iItemCount); posItem = ppItemVal; for (i = 0; i < iItemCount; i++) { ItemState = (OPCITEMSTATE)Marshal.PtrToStructure(posItem, typeof(OPCITEMSTATE)); if (Errors[i] == 0) { Values[i] = ItemState.vDataValue; TimeStamps[i] = ItemState.ftTimeStamp; Qualities[i] = ItemState.wQuality; } Marshal.DestroyStructure(posItem, typeof(OPCITEMSTATE)); // 05/02/08 Release memory //posItem = new IntPtr(posItem.ToInt32() + Marshal.SizeOf(typeof(OPCITEMSTATE))); // 1.0.0.5 10/06/21 Kishimoto Fixed for Memory Leak posItem = (IntPtr)(posItem.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); // 1.0.0.5 10/06/21 Kishimoto Fixed for Memory Leak } Marshal.FreeCoTaskMem(ppItemVal); Marshal.FreeCoTaskMem(ppErrors); break; } } catch (Exception exc) { MessageBox.Show(exc.ToString(), "SyncRead"); return(false); } // erase Errors System.GC.Collect(); //04/12/29 Revised Memory Leak return(true); }