/// <summary>
 /// Clear the queued requests and release the requests'
 /// MsgResponse lock signal.
 /// </summary>
 private void ClearRequests()
 {
     lock (SyncRoot)
     {
         MsgRequest[] reqs = GetRequests();
         if (reqs != null)
         {
             for (int i = 0; i < reqs.Length; i++)
             {
                 MsgRequest req = DequeueRequest(reqs[i].ReqMsgId);
                 if (req != null)
                 {
                     try
                     {
                         req.Response.SetResponse();
                     }
                     catch (ThreadStateException)
                     {
                         ; // do nothing
                     }
                 }
             }
         }
     }
 }
 /// <summary>
 /// Get the queued requests.
 /// </summary>
 /// <returns><see cref="MsgRequest"/> object array</returns>
 private MsgRequest[] GetRequests()
 {
     MsgRequest[] reqs = null;
     if (m_Requests.Count > 0)
     {
         // make a copy of all the request objects first
         reqs = new MsgRequest[m_Requests.Count];
         m_Requests.CopyTo(reqs, 0);
     }
     return(reqs);
 }
        /// <summary>
        /// Send a Hart-IP Request
        /// </summary>
        /// <param name="Request"><see cref="HartIPRequest"></see></param>
        /// <param name="MsgRsp"><see cref="MsgResponse"></see></param>
        /// <para>see the HartIPRequest.Command for HART specification references.</para>
        /// <returns>bool if it is success</returns>
        public bool SendHartRequest(HartIPRequest Request, MsgResponse MsgRsp)
        {
            bool bSuccess = false;

            if (Request == null)
            {
                throw new ArgumentException("Invalid argument in SendHartRequest.");
            }

            lock (SyncRoot)
            {
                m_Error = String.Empty;
                try
                {
                    if (m_RspMsgReader == null)
                    {
                        // Create a thread that is constantly reading on the input stream
                        m_bStopped          = false;
                        m_RspMsgReader      = new Thread(new ThreadStart(this.ReceiveMsg));
                        m_RspMsgReader.Name = "HartIPConnection";
                        m_RspMsgReader.Start();
                    }

                    // add the request object into the m_Requests list
                    MsgRequest MsgReq = new MsgRequest(Request.TransactionId, MsgRsp);
                    m_Requests.Add(MsgReq);

                    // send the request
                    bSuccess = SendRequest(Request);
                    LogMsg.Instance.Log(Request.ToString());
                }
                catch (SocketException se)
                {
                    m_Error = String.Format("SendHartRequest SocketException: ErrorCode:{0}. {1}",
                                            se.ErrorCode, se.Message);
                    LogMsg.Instance.Log("Error, " + m_Error, true);
                }
                catch (Exception e)
                {
                    m_Error = String.Format("SendHartRequest Exception: {0}", e.Message);
                    LogMsg.Instance.Log("Error, " + m_Error, true);
                }

                if (!bSuccess)
                {
                    LogMsg.Instance.Log("Error, Failed sending Request: " + Request.ToString(), true);
                    DequeueRequest(Request.TransactionId);
                }
            }

            return(bSuccess);
        }
        /// <summary>
        /// Continue get Hart-IP Response from the connected stream.
        /// Remove the received request from the list and release the
        /// MsgResponse lock signal.
        /// </summary>
        private void ReceiveMsg()
        {
            bool stoploop;

            lock (SyncRoot)
            {
                stoploop = m_bStopped;
            }

            while (!stoploop)
            {
                try
                {
                    HartIPResponse Rsp = GetResponse();
                    if (Rsp == null)
                    {
                        continue;
                    }

                    m_lLastActivityTime = DateTime.Now.Ticks;
                    if (Rsp.MessageType == HARTIPMessage.HART_ACK)
                    {
                        MsgRequest Req = DequeueRequest(Rsp.TransactionId);
                        if (Req != null)
                        {
                            Req.Response.SetResponse(Rsp);
                        }
                        else
                        {
                            // just in case can't find the request in the list
                            LogMsg.Instance.Log(Rsp.ToString());
                        }
                    }
                    else
                    {
                        if ((Rsp.MessageType == HARTIPMessage.HART_PUBLISH_NOTIFY) &&
                            (PublishedCmdNotify != null))
                        {
                            HartIPResponseArg Arg = new HartIPResponseArg(Rsp);
                            PublishedCmdNotify(this, Arg);
                        }
                        else
                        {
                            LogMsg.Instance.Log(Rsp.ToString());
                        }
                    }
                }
                catch (SocketException se)
                {
                    int nErrorCode = se.ErrorCode;
                    // socket receive timeout
                    if ((nErrorCode == 10060) || (nErrorCode == 10035))
                    {
                        if (m_nConnection != UDP)
                        {
                            break;
                        }
                    }
                    // socket closed, server close the connection or interrupted
                    else if ((nErrorCode == 995) || (nErrorCode == 10004) || (nErrorCode == 10054))
                    {
                        break;
                    }
                    else
                    {
                        LogMsg.Instance.Log("Error, ReceiveMsg SocketException: ErrorCode:" +
                                            nErrorCode + ". " + se.Message, true);
                        break;
                    }
                }
                catch (EndOfStreamException e)
                {
                    LogMsg.Instance.Log("Error, ReceiveMsg EndOfStreamException: " + e.Message, true);
                    break;
                }
                catch (IOException io)
                {
                    if (m_nConnection != TCP)
                    {
                        LogMsg.Instance.Log("Error, ReceiveMsg IOException: " + io.Message, true);
                        break;
                    }
                }
                catch (ObjectDisposedException obex)
                {
                    LogMsg.Instance.Log("Error, ReceiveMsg Expection :" + obex.Message, true);
                    break;
                }
                catch (ThreadStateException tsEx)
                {
                    // caller failed to release the lock signal and it will timeout
                    LogMsg.Instance.Log("Error, ReceiveMsg ThreadStateException: " + tsEx.Message, true);
                }
            }

            ClearRequests();
        }