/** Read all the messages in the queue */
        public List <TaggedBlob> Read()
        {
            List <TaggedBlob> result = new List <TaggedBlob>();

            // Wait until there's (probably) something new
            this.sharedMemory.BufferChangedEvent.WaitOne();

            if (this.sharedMemory.Mutex.WaitOneNoExcept())
            {
                try {
                    // Read the message count at the start of the buffer
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    int messageCount = this.sharedMemory.Reader.ReadInt32();

                    // Read over that many messages
                    for (int i = 0; i < messageCount; i++)
                    {
                        result.Add(TaggedBlob.Read(this.sharedMemory.Reader));
                    }

                    // Update the message count
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    this.sharedMemory.Writer.Write((int)0);
                }
                finally
                {
                    this.sharedMemory.Mutex.ReleaseMutex();
                }
            }
            return(result);
        }
        //---------------------------------------------------------------------
        // Reading and writing
        //---------------------------------------------------------------------

        public static TaggedBlob Read(BinaryReader reader)
            {
            TaggedBlob result = new TaggedBlob();
            result.Tag     = reader.ReadInt32();
            int cb         = reader.ReadInt32();
            result.Payload = reader.ReadBytes(cb);
            return result;
            }
        //---------------------------------------------------------------------
        // Reading and writing
        //---------------------------------------------------------------------

        public static TaggedBlob Read(BinaryReader reader)
        {
            TaggedBlob result = new TaggedBlob();

            result.Tag = reader.ReadInt32();
            int cb = reader.ReadInt32();

            result.Payload = reader.ReadBytes(cb);
            return(result);
        }
        public void Write(TaggedBlob blob, int msTimeout = -1)
        {
            if (this.sharedMemory.Mutex.WaitOneNoExcept(msTimeout))
            {
                try {
                    // Read the message count at the start of the buffer
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    int messageCount = this.sharedMemory.Reader.ReadInt32();

                    // Skip over that many messages
                    for (int i = 0; i < messageCount; i++)
                    {
                        TaggedBlob.Read(this.sharedMemory.Reader);
                    }

                    // Write the next string. 'May hit the buffer end and throw exception, but
                    // that's ok; we'll just be ignoring this message
                    blob.Write(this.sharedMemory.Writer);

                    // Update the message count
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    this.sharedMemory.Writer.Write(messageCount + 1);

                    // Let the reader know there's new stuff
                    this.sharedMemory.BufferChangedEvent.Set();
                }
                catch (Exception)
                {
                    // Ignore write errors; they'll be at buffer end. The actual exeption we
                    // see is a NotSupportedException thrown by the stream when asked to extend
                    // it's length
                }
                finally
                {
                    this.sharedMemory.Mutex.ReleaseMutex();
                }
            }
        }
        public void Write(TaggedBlob blob, int msTimeout=-1)
            {
            if (this.sharedMemory.Mutex.WaitOneNoExcept(msTimeout)) 
                {
                try {
                    // Read the message count at the start of the buffer
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    int messageCount = this.sharedMemory.Reader.ReadInt32();

                    // Skip over that many messages
                    for (int i = 0; i < messageCount; i++)
                        {
                        TaggedBlob.Read(this.sharedMemory.Reader);
                        }
                
                    // Write the next string. 'May hit the buffer end and throw exception, but 
                    // that's ok; we'll just be ignoring this message
                    blob.Write(this.sharedMemory.Writer);

                    // Update the message count
                    this.sharedMemory.MemoryViewStream.Seek(0, SeekOrigin.Begin);
                    this.sharedMemory.Writer.Write(messageCount + 1);
                
                    // Let the reader know there's new stuff
                    this.sharedMemory.BufferChangedEvent.Set();
                    }
                catch (Exception)
                    {
                    // Ignore write errors; they'll be at buffer end. The actual exeption we 
                    // see is a NotSupportedException thrown by the stream when asked to extend
                    // it's length
                    }
                finally
                    {
                    this.sharedMemory.Mutex.ReleaseMutex();
                    }
                }
            }