public IDataItem createByForm(IConnection aConnection, IWin32Window aOwner)
        {
            Connection lConnection  = (Connection)aConnection;
                DataItem lItem          = new DataItem();

                using (var lSetupForm = new ItemSetupForm(lConnection, lItem))
                {
                    if (lSetupForm.ShowDialog(aOwner) == DialogResult.OK)
                    {
                        lItem.mMemoryType   = lSetupForm.MemoryType;
                        lItem.DB            = lSetupForm.DB;
                        lItem.Byte          = lSetupForm.Byte;
                        lItem.Bit           = lSetupForm.Bit;
                        lItem.DataType      = lSetupForm.DataType;
                        lItem.FloatingP     = lSetupForm.FloatingP;
                        lItem.Signed        = lSetupForm.Signed;
                        lItem.Length        = lSetupForm.Length;

                        lConnection.addItem(lItem);
                    }
                    else
                    {
                        lItem = null;
                    }
                }

                return lItem;
        }
        public ItemSetupForm(Connection aConnectionS7PLCSim, DataItem aItemS7PLCSim)
        {
            mConnectionS7PLCSim = aConnectionS7PLCSim;
            InitializeComponent();

            MemoryType  = aItemS7PLCSim.mMemoryType;
            DataType    = aItemS7PLCSim.DataType;
            DB          = aItemS7PLCSim.DB;
            Bit         = aItemS7PLCSim.Bit;
            Byte        = aItemS7PLCSim.Byte;
            Signed      = aItemS7PLCSim.Signed;
            FloatingP   = aItemS7PLCSim.FloatingP;
            Length      = aItemS7PLCSim.Length;

            mConnectionS7PLCSim.ConnectionState += new EventHandler(onChange);
            updateForm();
        }
        public IDataItem createFromXML(IConnection aConnection, XmlTextReader aXMLTextReader)
        {
            Connection lConnection      = (Connection)aConnection;
                DataItem lItem              = new DataItem();
                XMLAttributeReader lReader  = new XMLAttributeReader(aXMLTextReader);

                lItem.mMemoryType = (EPLCMemoryType)Enum.Parse(typeof(EPLCMemoryType), lReader.getAttribute<String>("MemoryType"));
                if (lItem.mMemoryType == EPLCMemoryType.DB)
                {
                    lItem.DB = (int)lReader.getAttribute<UInt32>("DB");
                }

                lItem.DataType  = (PointDataTypeConstants)Enum.Parse(typeof(PointDataTypeConstants), lReader.getAttribute<String>("DataType"));
                lItem.Byte      = (int)lReader.getAttribute<UInt32>("Byte");

                if (lItem.DataType == PointDataTypeConstants.S7_Bit)
                {
                    lItem.Bit = (int)lReader.getAttribute<UInt32>("Bit");
                }
                else if (lItem.DataType == PointDataTypeConstants.S7_Byte || lItem.DataType == PointDataTypeConstants.S7_Word)
                {
                    lItem.Signed = lReader.getAttribute<Boolean>("Signed", lItem.Signed);
                }
                else if (lItem.DataType == PointDataTypeConstants.S7_DoubleWord)
                {
                    lItem.FloatingP = lReader.getAttribute<Boolean>("FloatingPoint", lItem.FloatingP);
                    if (lItem.FloatingP == false)
                    {
                        lItem.Signed = lReader.getAttribute<Boolean>("Signed", lItem.Signed);
                    }
                }

                if ((lItem.mMemoryType == EPLCMemoryType.I || lItem.mMemoryType == EPLCMemoryType.Q) && lItem.DataType != PointDataTypeConstants.S7_Bit)
                {
                    lItem.Length = (int)lReader.getAttribute<UInt32>("Length", 1);
                }

                lConnection.addItem(lItem);

                return lItem;
        }
        private void MainCycle(object aSender, ElapsedEventArgs aEventArgs)
        {
            long lStartMS = MiscUtils.TimerMS;

            if (mDisconnect == false)
            {
                try
                {
                    mS7ProSim.GetState();

                    if (mItemList.Count != 0)
                    {
                        #region Item List Changed

                            if (mItemListChanged)
                            {
                                mItemRWList.Clear();
                                mItemListLock.EnterReadLock();
                                //========================================
                                try
                                {
                                    mItemRWList.AddRange(mItemList);
                                    mItemListChanged = false;
                                }
                                finally
                                {
                                    //========================================
                                    mItemListLock.ExitReadLock();
                                }

                                mQLength    = 0;
                                mQOptimise  = true;
                            }
                            else if (mQOptimise)
                            {
                                mQOptimise = false;
                                optimise();
                            }

                        #endregion

                        if (mQLength > 0)
                        {
                            Task lQ = new Task(MC_Q_Read);
                            lQ.Start();

                            Task lIMDB = new Task(MC_IMDB_WriteRead);
                            lIMDB.Start();

                            Task.WaitAll(lQ, lIMDB);
                        }
                        else
                        {
                            int lCount = mItemRWList.Count;

                            for (int i = 0; i < lCount; i++)
                            {
                                mCurrentItem = mItemRWList[i];

                                if (mDisconnect) { break; }

                                #region Write

                                    if (mCurrentItem.mNeedWrite)
                                    {
                                        mWriteRequests = mWriteRequests + 1;
                                        mCurrentItem.write(mS7ProSim);
                                    }

                                #endregion

                                if (mDisconnect) { break; }

                                #region Read

                                    if (mCurrentItem.mNeedWrite != true)
                                    {
                                        mCurrentItem.read(mS7ProSim);
                                    }

                                #endregion

                                if (mDisconnect) { break; }

                                mSlowCounter = mSlowCounter + mDeltaSlow;
                                if (mSlowCounter >= 1.0D)
                                {
                                    mSlowCounter = mSlowCounter - 1.0D;
                                    Thread.Sleep(MiscUtils.TimeSlice);
                                }
                            }

                            mCurrentItem = null;
                        }
                    }
                }
                catch (Exception lExc)
                {
                    mDisconnect = true;
                    raiseConnectionError(lExc.Message);
                }
            }

            mMainCycleTimeMS = MiscUtils.TimerMS - lStartMS;

            if (mDisconnect)
            {
                mS7ProSim.EndScanNotify();
                mS7ProSim.Disconnect();

                mConnected = false;
                raiseConnectionState();
                mCycleEndEvent.Set();
                mDisconnectEvent.Set();
            }
            else
            {
                mMainCycleTimer.Start();
                mCycleEndEvent.Set();
            }
        }
        private void MC_IMDB_WriteRead()
        {
            int lCount = mItemRWList.Count;

            for (int i = 0; i < lCount; i++)
            {
                mCurrentItem = mItemRWList[i];

                if (mDisconnect) { break; }

                if (mCurrentItem.mMemoryType != EPLCMemoryType.Q)
                {
                    try
                    {
                        #region Write

                            if (mCurrentItem.mNeedWrite)
                            {
                                mWriteRequests = mWriteRequests + 1;
                                mCurrentItem.write(mS7ProSim);
                            }

                        #endregion

                        if (mDisconnect) { break; }

                        #region Read

                            if (mCurrentItem.mNeedWrite != true)
                            {
                                mCurrentItem.read(mS7ProSim);
                            }

                        #endregion

                        if (mDisconnect) { break; }

                        mSlowCounter = mSlowCounter + mDeltaSlow;
                        if (mSlowCounter >= 1.0D)
                        {
                            mSlowCounter = mSlowCounter - 1.0D;

                            Thread.Sleep(MiscUtils.TimeSlice);
                        }
                    }
                    catch (Exception lExc)
                    {
                        mDisconnect = true;
                        raiseConnectionError(lExc.Message);
                    }
                }

                mCurrentItem = null;
            }
        }
        protected virtual void Dispose(bool aDisposing)
        {
            if (!mDisposed)
                {
                    if (aDisposing)
                    {
                        mS7ProSim.ConnectionError -= onConnectionError;

                        mItemList.Clear();
                        mItemRWList.Clear();
                        mCurrentItem = null;

                        if (mItemListLock != null)
                        {
                            mItemListLock.Dispose();
                            mItemListLock = null;
                        }

                        if (mMainCycleTimer != null)
                        {
                            mMainCycleTimer.Dispose();
                            mMainCycleTimer = null;
                        }

                        if (mDisconnectEvent != null)
                        {
                            mDisconnectEvent.Dispose();
                            mDisconnectEvent = null;
                        }

                        if (mCycleEndEvent != null)
                        {
                            mCycleEndEvent.Dispose();
                            mCycleEndEvent = null;
                        }
                    }

                    mDisposed = true;
                }
        }
        public void removeItem(DataItem aItem)
        {
            ConnectionState -= aItem.onConnectionStateChanged;

                mItemListLock.EnterWriteLock();
                //========================================
                try
                {
                    mItemList.Remove(aItem);
                    mItemListChanged = true;
                }
                finally
                {
                    //========================================
                    mItemListLock.ExitWriteLock();
                }
        }
        public void addItem(DataItem aItem)
        {
            aItem.mConnection   = this;
                ConnectionState     += new EventHandler(aItem.onConnectionStateChanged);
                aItem.initAccess();

                mItemListLock.EnterWriteLock();
                //========================================
                try
                {
                    mItemList.Add(aItem);
                    mItemListChanged = true;
                }
                finally
                {
                    //========================================
                    mItemListLock.ExitWriteLock();
                }
        }
        private void                                        MC_IMDB_WriteRead()
        {
            int lCount = mItemRWList.Count;

            for (int i = 0; i < lCount; i++)
            {
                mCurrentItem = mItemRWList[i];

                if (mDisconnect)
                {
                    break;
                }

                if (mCurrentItem.mMemoryType != EPLCMemoryType.Q)
                {
                    try
                    {
                        #region Write

                        if (mCurrentItem.mNeedWrite)
                        {
                            mWriteRequests = mWriteRequests + 1;
                            mCurrentItem.write(mS7ProSim);
                        }

                        #endregion

                        if (mDisconnect)
                        {
                            break;
                        }

                        #region Read

                        if (mCurrentItem.mNeedWrite != true)
                        {
                            mCurrentItem.read(mS7ProSim);
                        }

                        #endregion

                        if (mDisconnect)
                        {
                            break;
                        }

                        mSlowCounter = mSlowCounter + mDeltaSlow;
                        if (mSlowCounter >= 1.0D)
                        {
                            mSlowCounter = mSlowCounter - 1.0D;

                            Thread.Sleep(MiscUtils.TimeSlice);
                        }
                    }
                    catch (Exception lExc)
                    {
                        mDisconnect = true;
                        raiseConnectionError(lExc.Message);
                    }
                }

                mCurrentItem = null;
            }
        }
        private void                                        MainCycle(object aSender, ElapsedEventArgs aEventArgs)
        {
            long lStartMS = MiscUtils.TimerMS;

            if (mDisconnect == false)
            {
                try
                {
                    mS7ProSim.GetState();

                    if (mItemList.Count != 0)
                    {
                        #region Item List Changed

                        if (mItemListChanged)
                        {
                            mItemRWList.Clear();
                            mItemListLock.EnterReadLock();
                            //========================================
                            try
                            {
                                mItemRWList.AddRange(mItemList);
                                mItemListChanged = false;
                            }
                            finally
                            {
                                //========================================
                                mItemListLock.ExitReadLock();
                            }

                            mQLength   = 0;
                            mQOptimise = true;
                        }
                        else if (mQOptimise)
                        {
                            mQOptimise = false;
                            optimise();
                        }

                        #endregion

                        if (mQLength > 0)
                        {
                            Task lQ = new Task(MC_Q_Read);
                            lQ.Start();

                            Task lIMDB = new Task(MC_IMDB_WriteRead);
                            lIMDB.Start();

                            Task.WaitAll(lQ, lIMDB);
                        }
                        else
                        {
                            int lCount = mItemRWList.Count;

                            for (int i = 0; i < lCount; i++)
                            {
                                mCurrentItem = mItemRWList[i];

                                if (mDisconnect)
                                {
                                    break;
                                }

                                #region Write

                                if (mCurrentItem.mNeedWrite)
                                {
                                    mWriteRequests = mWriteRequests + 1;
                                    mCurrentItem.write(mS7ProSim);
                                }

                                #endregion

                                if (mDisconnect)
                                {
                                    break;
                                }

                                #region Read

                                if (mCurrentItem.mNeedWrite != true)
                                {
                                    mCurrentItem.read(mS7ProSim);
                                }

                                #endregion

                                if (mDisconnect)
                                {
                                    break;
                                }

                                mSlowCounter = mSlowCounter + mDeltaSlow;
                                if (mSlowCounter >= 1.0D)
                                {
                                    mSlowCounter = mSlowCounter - 1.0D;
                                    Thread.Sleep(MiscUtils.TimeSlice);
                                }
                            }

                            mCurrentItem = null;
                        }
                    }
                }
                catch (Exception lExc)
                {
                    mDisconnect = true;
                    raiseConnectionError(lExc.Message);
                }
            }

            mMainCycleTimeMS = MiscUtils.TimerMS - lStartMS;

            if (mDisconnect)
            {
                mS7ProSim.EndScanNotify();
                mS7ProSim.Disconnect();

                mConnected = false;
                raiseConnectionState();
                mCycleEndEvent.Set();
                mDisconnectEvent.Set();
            }
            else
            {
                mMainCycleTimer.Start();
                mCycleEndEvent.Set();
            }
        }