public void Close() { lock (syncLock) { if (inbox != null) { inbox.Close(); if (emptyBoxEvent != null) { emptyBoxEvent.Close(); } } } }
/// <summary> /// Forces the lock release, regardless of the current lock count. /// </summary> /// <remarks> /// It is not an error to call this if the lock is not currently held. /// </remarks> public void ReleaseAll() { lock (syncLock) { if (initLock == null) { return; } initLock.Close(); initLock = null; cLock = 0; } }
/// <summary> /// This method closes the inbox. All successful calls to <see cref="Open" /> must /// be matched with a call to Close() to ensure that system resources /// are released in a timely manner. Note that it is OK to call Close() /// even if the shared memory block is not open. This method is threadsafe. /// </summary> public unsafe void Close() { lock (syncLock) { if (sharedMem == null) { return; } byte *p; p = sharedMem.Lock(); // Indicate that we're not listening any more if (p != null) { p[InboxListeningOffset] = 0; sharedMem.Unlock(); } #if WINFULL // Wait up to 5 seconds for the receive thread to stop normally before // forcing the issue. int cWaits = 0; do { killThread = true; // Kill the receive thread newMsgEvent.Set(); cWaits++; if (cWaits == 5) { recvThread.Abort(); } } while (!recvThread.Join(1000)); #else newMsgEvent.Set(); killThread = true; Thread.Sleep(5000); recvThread.Abort(); recvThread.Join(); #endif sharedMem.Close(); // Release unmanaged resources newMsgEvent.Close(); emptyBoxEvent.Close(); sharedMem = null; onReceive = null; onDispatch = null; } }
/// <summary> /// Attempts to acquire the global application lock. /// </summary> /// <remarks> /// <note> /// <see cref="Release" /> should be called promptly when the /// application terminates to release the lock. /// </note> /// </remarks> /// <exception cref="GlobalLockException">Thrown when there's a problem acquiring the lock.</exception> public unsafe void Lock() { EnhancedMemoryStream ms; byte *pMem; byte[] buf; Assembly assembly; string path; lock (syncLock) { if (initLock != null) { cLock++; // The lock is already acquired return; } try { // Use a global shared memory block to enforce the lock. assembly = Assembly.GetEntryAssembly(); if (assembly == null) { assembly = Assembly.GetCallingAssembly(); } path = Helper.StripFileScheme(assembly.CodeBase); ms = new EnhancedMemoryStream(4096); ms.WriteString16(path); initLock = new SharedMem(); initLock.Open("LT.Lock." + appName, 4096, SharedMem.OpenMode.CREATE_OPEN); pMem = initLock.Lock(); if (pMem[0] != 0 || pMem[1] != 0) { buf = new byte[initLock.Size]; for (int i = 0; i < buf.Length; i++) { buf[i] = pMem[i]; } ms = new EnhancedMemoryStream(buf); initLock.Unlock(); initLock.Close(); initLock = null; throw new GlobalLockException("Global lock is already acquired by [{0}].", ms.ReadString16()); } buf = ms.ToArray(); for (int i = 0; i < buf.Length; i++) { pMem[i] = buf[i]; } initLock.Unlock(); } catch (Exception e) { throw new GlobalLockException(e); } } cLock++; }