/// <summary>
        /// If possible, this method dequeues a read from the read queue and starts it.
        /// This is only possible if all of the following are true:
        ///  1) any previous read has completed
        ///  2) there's a read in the queue
        ///  3) and the stream is ready.
        /// 
        /// This method is thread safe.
        /// </summary>
        private void MaybeDequeueRead(object ignore)
        {
            lock (lockObj)
            {
                if ((flags & kClosed) > 0)
                {
                    readQueue.Clear();
                    return;
                }

                if ((currentRead == null) && (stream != null))
                {
                    if((flags & kPauseReads) > 0)
                    {
                        // Don't do any reads yet.
                        // We're waiting for TLS negotiation to start and/or finish.
                    }
                    else if(readQueue.Count > 0)
                    {
                        // Get the next object in the read queue
                        Object nextRead = readQueue.Dequeue();

                        if (nextRead is AsyncSpecialPacket)
                        {
                            // Next read packet is a special instruction packet.
                            // Right now this can only mean a StartTLS instruction.
                            AsyncSpecialPacket specialRead = (AsyncSpecialPacket)nextRead;

                            // Update flags - this flag will be unset when TLS finishes
                            flags |= kPauseReads;

                            // And attempt to start TLS
                            // This method won't do anything unless both kPauseReads and kPauseWrites are set.
                            MaybeStartTLS();
                        }
                        else
                        {
                            // Get the new current read AsyncReadPacket
                            currentRead = (AsyncReadPacket)nextRead;

                            // Start time-out timer
                            if (currentRead.timeout >= 0)
                            {
                                readTimer = new System.Threading.Timer(new TimerCallback(stream_DidNotRead),
                                                                       currentRead,
                                                                       currentRead.timeout,
                                                                       Timeout.Infinite);
                            }

                            // Do we have any overflow data that we've already read from the stream?
                            if (readOverflow != null)
                            {
                                // Start reading from the overflow
                                DoReadOverflow();
                            }
                            else
                            {
                                // Start reading from the stream
                                DoStartRead();
                            }
                        }
                    }
                    else if((flags & kCloseAfterReads) > 0)
                    {
                        if ((flags & kCloseAfterWrites) > 0)
                        {
                            if ((writeQueue.Count == 0) && (currentWrite == null))
                            {
                                Close(null);
                            }
                        }
                        else
                        {
                            Close(null);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Ends the current read by disposing and nullifying the read timer,
        /// and then nullifying the current read.
        /// </summary>
        private void EndCurrentRead()
        {
            if (readTimer != null)
            {
                readTimer.Dispose();
                readTimer = null;
            }

            currentRead = null;
        }