/// <summary>
        /// The worker thread entry point for polling the MailSlot. Threads will queue until a Mutex becomes
        /// available for a particular channel.
        /// </summary>
        /// <param name="state"></param>
        private void MailSlotChecker(object state)
        {
            MailSlotThreadInfo info = (MailSlotThreadInfo)state;
            bool   isOwner          = false;
            string mutextKey        = string.Concat(mutexNetworkDispatcher, ".", info.ChannelName);

            using (Mutex mutex = new Mutex(true, mutextKey, out isOwner))
            {
                // if doesn't own mutex then wait
                if (!isOwner)
                {
                    try
                    {
                        mutex.WaitOne();
                        isOwner = true;
                    }
                    catch (ThreadInterruptedException) { } // shut down thread
                    catch (AbandonedMutexException)
                    {
                        // This thread is now the owner
                        isOwner = true;
                    }
                }

                if (isOwner)
                {
                    // enter message read loop
                    ProcessMessages(info);

                    // if this thread owns mutex then release it
                    mutex.ReleaseMutex();
                }
            }
        }
        /// <summary>
        /// Helper method starts up a new listener thread for a given channel.
        /// </summary>
        /// <param name="channelName">The channel name.</param>
        /// <returns></returns>
        private MailSlotThreadInfo StartNewThread(string channelName)
        {
            // create and start the thread at low priority
            Thread thread = new Thread(new ParameterizedThreadStart(MailSlotChecker));

            thread.Priority     = ThreadPriority.Lowest;
            thread.IsBackground = true;
            MailSlotThreadInfo info = new MailSlotThreadInfo(channelName, thread);

            thread.Start(info);
            return(info);
        }
        /// <summary>
        /// This helper method puts the thread into a read message
        /// loop.
        /// </summary>
        /// <param name="info"></param>
        private void ProcessMessages(MailSlotThreadInfo info)
        {
            int bytesToRead = 512, maxMessageSize = 0, messageCount = 0, readTimeout = 0;

            // for as long as thread is alive and the channel is registered then act as the MailSlot reader
            while (!disposed && activeThreads.ContainsKey(info.ChannelName))
            {
                // if the channel mailslot is not open try to open it
                if (!info.HasValidFileHandle)
                {
                    info.FileHandle = Native.CreateMailslot(string.Concat(mailSlotIdentifier, info.ChannelName), 0, Native.MAILSLOT_WAIT_FOREVER, IntPtr.Zero);
                }

                // if there is a valid read handle try to read messages
                if (info.HasValidFileHandle)
                {
                    byte[] buffer    = new byte[bytesToRead];
                    uint   bytesRead = 0;
                    // this blocks until a message is received, the message cannot be buffered with overlap structure
                    // so the bytes array must be larger than the current item in order to read the complete message
                    while (Native.ReadFile(info.FileHandle, buffer, (uint)bytesToRead, out bytesRead, IntPtr.Zero))
                    {
                        ProcessMessage(buffer, bytesRead);
                        // reset buffer size
                        bytesToRead = 512;
                        buffer      = new byte[bytesToRead];
                    }
                    int code = Marshal.GetLastWin32Error();
                    switch (code)
                    {
                    case Native.ERROR_INSUFFICIENT_BUFFER:
                        // insufficent buffer size, we need to the increase buffer size to read the current item
                        Native.GetMailslotInfo(info.FileHandle, ref maxMessageSize, ref bytesToRead, ref messageCount, ref readTimeout);
                        break;

                    case Native.ERROR_INVALID_HANDLE:
                        // close handle if invalid
                        if (info.HasValidFileHandle)
                        {
                            Native.CloseHandle(info.FileHandle);
                            info.FileHandle = IntPtr.Zero;
                        }
                        break;

                    case Native.ERROR_HANDLE_EOF:
                        // read handle has been closed
                        info.FileHandle = IntPtr.Zero;
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// Unregisters the current instance from the given channel. No more messages will be
        /// processed, and another process will be allowed to obtain the listener lock.
        /// </summary>
        /// <param name="channelName"></param>
        public void UnRegisterChannel(string channelName)
        {
            MailSlotThreadInfo info = null;

            if (activeThreads.TryGetValue(channelName, out info))
            {
                // only lock if changing
                lock (lockObj)
                {
                    // double check has not been modified before lock
                    if (activeThreads.TryGetValue(channelName, out info))
                    {
                        // removing form hash shuts down the thread loop
                        activeThreads.Remove(channelName);
                    }
                }
                if (info != null)
                {
                    // close any read handles
                    if (info.HasValidFileHandle)
                    {
                        Native.CloseHandle(info.FileHandle);
                    }
                    if (info.Thread.IsAlive)
                    {
                        // interrupt incase of asleep thread
                        info.Thread.Interrupt();
                    }
                    if (info.Thread.IsAlive)
                    {
                        // attempt to join thread
                        if (!info.Thread.Join(500))
                        {
                            // if no response within timeout, force abort
                            //info.Thread.Abort(); //Do nothing
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Helper method starts up a new listener thread for a given channel.
 /// </summary>
 /// <param name="channelName">The channel name.</param>
 /// <returns></returns>
 private MailSlotThreadInfo StartNewThread(string channelName)
 {
     // create and start the thread at low priority
     Thread thread = new Thread(new ParameterizedThreadStart(MailSlotChecker));
     thread.Priority = ThreadPriority.Lowest;
     thread.IsBackground = true;
     MailSlotThreadInfo info = new MailSlotThreadInfo(channelName, thread);
     thread.Start(info);
     return info;
 }
        /// <summary>
        /// This helper method puts the thread into a read message
        /// loop.
        /// </summary>
        /// <param name="info"></param>
        private void ProcessMessages(MailSlotThreadInfo info)
        {
            int bytesToRead = 512, maxMessageSize = 0, messageCount = 0, readTimeout = 0;
            // for as long as thread is alive and the channel is registered then act as the MailSlot reader
            while (!disposed && activeThreads.ContainsKey(info.ChannelName))
            {
                // if the channel mailslot is not open try to open it
                if (!info.HasValidFileHandle)
                {
                    info.FileHandle = Native.CreateMailslot(string.Concat(mailSlotIdentifier, info.ChannelName), 0, Native.MAILSLOT_WAIT_FOREVER, IntPtr.Zero);
                }

                // if there is a valid read handle try to read messages
                if (info.HasValidFileHandle)
                {
                    byte[] buffer = new byte[bytesToRead];
                    uint bytesRead = 0;
                    // this blocks until a message is received, the message cannot be buffered with overlap structure
                    // so the bytes array must be larger than the current item in order to read the complete message
                    while (Native.ReadFile(info.FileHandle, buffer, (uint)bytesToRead, out bytesRead, IntPtr.Zero))
                    {
                        ProcessMessage(buffer, bytesRead);
                        // reset buffer size
                        bytesToRead = 512;
                        buffer = new byte[bytesToRead];
                    }
                    int code = Marshal.GetLastWin32Error();
                    switch (code)
                    {
                        case Native.ERROR_INSUFFICIENT_BUFFER:
                            // insufficent buffer size, we need to the increase buffer size to read the current item
                            Native.GetMailslotInfo(info.FileHandle, ref maxMessageSize, ref bytesToRead, ref messageCount, ref readTimeout);
                            break;
                        case Native.ERROR_INVALID_HANDLE:
                            // close handle if invalid
                            if (info.HasValidFileHandle)
                            {
                                Native.CloseHandle(info.FileHandle);
                                info.FileHandle = IntPtr.Zero;
                            }
                            break;
                        case Native.ERROR_HANDLE_EOF:
                            // read handle has been closed
                            info.FileHandle = IntPtr.Zero;
                            break;
                    }
                }
            }
        }