public void StartListening(Action <Stream> messageHandler)
        {
            using (EneterTrace.Entering())
            {
                using (ThreadLock.Lock(myListeningManipulatorLock))
                {
                    if (IsListening)
                    {
                        string aMessage = TracedObject + ErrorHandler.IsAlreadyListening;
                        EneterTrace.Error(aMessage);
                        throw new InvalidOperationException(aMessage);
                    }

                    if (messageHandler == null)
                    {
                        throw new ArgumentNullException("The input parameter messageHandler is null.");
                    }

                    // If this was not the first instance of the mutex, then it means, that the listener with the same
                    // memory mapped file already exists.
                    bool aFirstInstanceFlag;
                    try
                    {
                        myOnlyListeningInstance = new Mutex(false, myMemoryMappedFileName + "_OnlyListenerMutex", out aFirstInstanceFlag);
                    }
                    catch (Exception err)
                    {
                        EneterTrace.Error(TracedObject + "failed to recognize if this is only listener.", err);
                        throw;
                    }
                    if (!aFirstInstanceFlag)
                    {
                        string anErrorMessage = TracedObject + "cannot start listening because a listener with the same memory mapped file already exists.";
                        EneterTrace.Error(anErrorMessage);
                        throw new InvalidOperationException(anErrorMessage);
                    }

                    try
                    {
                        myStopListeningRequested = false;
                        myMessageHandler         = messageHandler;

                        // IF the listener will work with already existing memory mapped file.
                        if (myUseExistingMemoryMappedFile)
                        {
                            // Open existing synchronization event handles.
                            mySharedMemoryCreated = EventWaitHandleExt.OpenExisting(myMemoryMappedFileName + "_ResponseSharedMemoryCreated", myOpenTimeout);
                            mySharedMemoryFilled  = EventWaitHandleExt.OpenExisting(myMemoryMappedFileName + "_SharedMemoryFilled", myOpenTimeout);
                            mySharedMemoryReady   = EventWaitHandleExt.OpenExisting(myMemoryMappedFileName + "_SharedMemoryReady", myOpenTimeout);

                            // Wait until the memory mapped file exist.
                            // Note: The file shall be created by SharedMemorySender.
                            if (!mySharedMemoryCreated.WaitOne(myOpenTimeout))
                            {
                                throw new InvalidOperationException(TracedObject + "failed to open memory mapped file because it does not exist.");
                            }

                            // Open existing shared memory file.
                            myMemoryMappedFile = MemoryMappedFile.OpenExisting(myMemoryMappedFileName);
                        }
                        else
                        {
                            // Create synchronization event handles.
                            bool aDummy;
                            mySharedMemoryCreated = new EventWaitHandle(false, EventResetMode.ManualReset, myMemoryMappedFileName + "_ResponseSharedMemoryCreated", out aDummy, myEventWaitHandleSecurity);
                            mySharedMemoryFilled  = new EventWaitHandle(false, EventResetMode.AutoReset, myMemoryMappedFileName + "_SharedMemoryFilled", out aDummy, myEventWaitHandleSecurity);
                            mySharedMemoryReady   = new EventWaitHandle(false, EventResetMode.AutoReset, myMemoryMappedFileName + "_SharedMemoryReady", out aDummy, myEventWaitHandleSecurity);

                            // Create the new memory mapped file.
                            myMemoryMappedFile = MemoryMappedFile.CreateNew(myMemoryMappedFileName, myMaxMessageSize, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, myMemmoryMappedFileSecurity, HandleInheritability.None);

                            // Indicate the memory mapped file was created.
                            mySharedMemoryCreated.Set();
                        }

                        // Start the listener that will read messages from the shared memory.
                        myListeningThread = new Thread(DoListening);
                        myListeningThread.Start();

                        // Wait until the listening thread is ready.
                        myListeningStartedEvent.WaitOne(5000);
                    }
                    catch (Exception err)
                    {
                        EneterTrace.Error(TracedObject + ErrorHandler.FailedToStartListening, err);

                        try
                        {
                            // Clear after failed start
                            StopListening();
                        }
                        catch
                        {
                            // We tried to clean after failure. The exception can be ignored.
                        }

                        throw;
                    }
                }
            }
        }
        // Note: in order to be consistent with other messagings (e.g. TcpMessaging) value 0 for timeouts mean infinite time.
        public SharedMemorySender(string memoryMappedFileName, bool useExistingMemoryMappedFile, TimeSpan openTimeout, TimeSpan sendTimeout, int maxMessageSize, MemoryMappedFileSecurity memoryMappedFileSecurity)
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    mySendTimeout = (sendTimeout == TimeSpan.Zero) ? TimeSpan.FromMilliseconds(-1) : sendTimeout;
                    myUseExistingMemoryMappedFile = useExistingMemoryMappedFile;
                    myMaxMessageSize = maxMessageSize;

                    // If the shared memory file is created by SharedMemoryReceiver then open existing one.
                    if (useExistingMemoryMappedFile)
                    {
                        TimeSpan anOpenTimeout = (openTimeout == TimeSpan.Zero) ? TimeSpan.FromMilliseconds(-1) : openTimeout;

                        // Try to open synchronization handlers.
                        mySharedMemoryReady   = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_SharedMemoryReady", anOpenTimeout);
                        mySharedMemoryFilled  = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_SharedMemoryFilled", anOpenTimeout);
                        mySharedMemoryCreated = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_ResponseSharedMemoryCreated", anOpenTimeout);

                        // Wait until the memory mapped file exist and then open it.
                        // Note: it shall be created by SharedMemoryReceiver.
                        if (!mySharedMemoryCreated.WaitOne(anOpenTimeout))
                        {
                            throw new InvalidOperationException(TracedObject + "failed to open memory mapped file because it does not exist.");
                        }
                        myMemoryMappedFile = MemoryMappedFile.OpenExisting(memoryMappedFileName);
                    }
                    // If the shared memory file shall be created by SharedMemorySender.
                    else
                    {
                        EventWaitHandleSecurity anEventWaitHandleSecurity = null;
                        if (memoryMappedFileSecurity != null)
                        {
                            // Create the security for the WaitHandle logic.
                            anEventWaitHandleSecurity = new EventWaitHandleSecurity();
                            anEventWaitHandleSecurity.SetSecurityDescriptorSddlForm("S:(ML;;NW;;;LW)");
                            SecurityIdentifier        aSid         = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
                            EventWaitHandleAccessRule anAccessRule = new EventWaitHandleAccessRule(aSid,
                                                                                                   EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize,
                                                                                                   AccessControlType.Allow);
                            anEventWaitHandleSecurity.AddAccessRule(anAccessRule);
                        }

                        // Create synchronization handlers.
                        bool aDummy;
                        mySharedMemoryReady   = new EventWaitHandle(false, EventResetMode.AutoReset, memoryMappedFileName + "_SharedMemoryReady", out aDummy, anEventWaitHandleSecurity);
                        mySharedMemoryFilled  = new EventWaitHandle(false, EventResetMode.AutoReset, memoryMappedFileName + "_SharedMemoryFilled", out aDummy, anEventWaitHandleSecurity);
                        mySharedMemoryCreated = new EventWaitHandle(false, EventResetMode.ManualReset, memoryMappedFileName + "_ResponseSharedMemoryCreated", out aDummy, anEventWaitHandleSecurity);

                        // Create the memory mapped file.
                        myMemoryMappedFile = MemoryMappedFile.CreateNew(memoryMappedFileName, maxMessageSize, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, memoryMappedFileSecurity, HandleInheritability.None);

                        // Indicate the shared memory is created.
                        mySharedMemoryCreated.Set();
                    }

                    myMemoryMappedFileStream = myMemoryMappedFile.CreateViewStream();
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "failed to create SharedMemorySender.", err);

                    // Dispose resources alocated so far.
                    Dispose();

                    throw;
                }
            }
        }