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; } } }