/// <summary>
        /// main processing loop.  This is where all messages get processed.
        /// </summary>
        private void MainQueueHandling()
        {
            m_state = QH_ThreadState.RUNNING_IDLE;
            CrystalisHIDAsynchCommand qe = null;
            UEI.HidIf.CommandType retVal = UEI.HidIf.CommandType.ResponseSuccess;
            while(! m_quitNow)
            {
                // make sure we are clear before next loop.
                qe = null;

                // the normal.. 
                // check if it looks like we have anything..
                if (m_messages.Count > 0)
                {
                    if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                    {
                        UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::MainQueueHandling  msg rcvd",
                                                        Thread.CurrentThread.GetHashCode()));
                    }

                    // lock if it looks like we do..
                    lock(this)
                    {
                        // check again just in case.
                        // note that this detail prob. isn't required 
                        // if it is just ONE task servicing messages.. 
                        // but just in case we ever go to multiple workers
                        // this design will work.
                        if (m_messages.Count > 0)
                        {
                            if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                            {
                                UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::MainQueueHandling  msg dequeued",
                                                                Thread.CurrentThread.GetHashCode()));
                            }   
                        
                            qe = m_messages.Dequeue();
                        }
                    }
                    if(qe != null)
                    {
                        if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                        {
                            UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::MainQueueHandling  processing msg",
                                                            Thread.CurrentThread.GetHashCode()));
                        }

                        // do the command.
                        m_state = QH_ThreadState.RUNNING_BUSY;
                        retVal = qe.DoCommandProcess(m_crys_comm);                    
                        m_state = QH_ThreadState.RUNNING_IDLE;

                        if(retVal == UEI.HidIf.CommandType.PCErrorDeviceNotOpen)
                        {
                            // this message is unequivocal.. 
                            m_remoteConnected = false;
                        }
                    }
                    // done with message.
                    qe = null;
                }
                else
                {
                    // default behavior.. when not servicing a queue request, ping the remote then sleep for 1 second.
                    retVal = m_crys_comm.PingRemote();
                    if(retVal != UEI.HidIf.CommandType.ResponseSuccess)
                    {
                        m_remoteConnected = false;
                    }
                    else
                    {
                        m_remoteConnected = true;
                    }
                    // wait for one second, or until this event is 'Set'
                    m_pingWait.WaitOne(QUEUE_SLEEP,false);
                }
                // fire our remote connected/disconnected events if needed
                HandleRemoteConnected();
            }
            // we are done.
            m_state = QH_ThreadState.ENDED;
        }
        /// <summary>
        /// deal with all the potential thread states (performed during message submission).
        /// if this thread is in any funny state at all, try to abort then restart
        /// </summary>
        private void ThreadingStateHandler()
        {
            if(m_runningThread != null)
            {
                if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                {
                    UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::SubmitMessage threadstate:{1}",
                                                                  Thread.CurrentThread.GetHashCode(),
                                                                  m_runningThread.ThreadState)); 
                }
                switch(m_runningThread.ThreadState)
                {
                    case ThreadState.Aborted:
                    case ThreadState.AbortRequested:
                    case ThreadState.Stopped:
                    case ThreadState.StopRequested:
                        // we are in a 'bad state'.. try to abort then restart.
                        if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                        {

                            UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::SubmitMessage end state detected.. aborting",
                                                                          Thread.CurrentThread.GetHashCode()));
                        }

                        // abort this thread.
                        m_runningThread.Abort();
                        if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                        {
                            UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::SubmitMessage end state detected.. awaiting full stop",
                                                                          Thread.CurrentThread.GetHashCode()));
                        }
                        // wait until we are done.
                        while(m_runningThread.ThreadState != ThreadState.Stopped);
                        m_runningThread = null;
                        m_state = QH_ThreadState.NOT_STARTED;
                        if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                        {
                            UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::SubmitMessage end state detected.. restarting",
                                                                          Thread.CurrentThread.GetHashCode()));
                        }

                        // now restart..
                        Start();
                        break;
                    default:
                        // all other states we don't care about.
                        break;
                }
            }
            else
            {
                m_state = QH_ThreadState.NOT_STARTED;
                if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                {
                    UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::SubmitMessage ... starting",
                                                                  Thread.CurrentThread.GetHashCode()));
                }

                Start();
            }
        }
        /// <summary>
        /// start message processing (and our one worker thread)
        /// </summary>
        /// <returns> StartErr </returns>
        public StartErr Start()
        {
            StartErr retVal = StartErr.SUCCESS;
            if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
            {
                UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::Start",
                                                Thread.CurrentThread.GetHashCode()));
            }

            m_quitNow = false;
            if(m_state == QH_ThreadState.NOT_STARTED)
            {
                m_state = QH_ThreadState.STARTING;
                
                if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                {
                    UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::Start  starting..",
                                                    Thread.CurrentThread.GetHashCode()));
                }
                
                m_runningThread = new Thread(MainQueueHandling);
                m_runningThread.IsBackground = true;
                m_runningThread.Start();
            }
            else
            {
                if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
                {
                    UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::Start  already started!",
                                                    Thread.CurrentThread.GetHashCode()));
                }
                retVal = StartErr.ALREADY_STARTED;
            }
            return retVal;
        }
 /// <summary>
 /// quit signal.  All the caller can do is tell us to go away.. 
 /// </summary>
 public void QuitNow()
 {
     const int WAIT_FOR_STOP = 15;
     const int WAIT_DURATION = 50; // milliseconds.
     int m_retry_count = 0;
     
     if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
     {
         UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::QuitNow ENTER",
                                                       Thread.CurrentThread.GetHashCode()));
     }
     if(m_runningThread != null)
     {
         m_quitNow = true;
         m_pingWait.Set();
         
         if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
         {
             UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::QuitNow  signal sent..",
                                                           Thread.CurrentThread.GetHashCode()));
         }
         
         while(      (m_retry_count < WAIT_FOR_STOP                          )
               &&    (m_runningThread.ThreadState != ThreadState.Stopped)   )
         {
             if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
             {
                 UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::QuitNow  waiting to complete",
                                                               Thread.CurrentThread.GetHashCode()));
             }
             Thread.Sleep(WAIT_DURATION);
             m_retry_count++;
         }
         if(m_runningThread.ThreadState != ThreadState.Stopped)
         {
             if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
             {
                 UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::QuitNow  abort required",
                                                               Thread.CurrentThread.GetHashCode()));
             }
             m_runningThread.Abort();
         }
     }
     m_runningThread = null;
     m_state = QH_ThreadState.NOT_STARTED;
     if(UEI.HidIf.HidIFTraceSwitch.trace_switch.Level >= System.Diagnostics.TraceLevel.Info)
     {
         UEI.Diagnostics.Debug.WriteLine(String.Format("({0})HIDQueueHander::QuitNow  EXIT",
                                                       Thread.CurrentThread.GetHashCode()));
     }
     
 }