// // Tries to take ownership of a file lock. // private static FileLock WaitInternal(string name, int timeout) { var fileLock = BuildFileLock(name); try { if (timeout != 0 && timeout != -1) { throw new NotImplementedException("FileLock.Wait() is implemented only for timeouts 0 or -1."); } var overlapped = new NativeOverlapped(); bool hasHandle = NativeLockFile.LockFileEx( fileLock.SafeFileHandle, NativeLockFile.LOCKFILE_EXCLUSIVE_LOCK | (timeout == 0 ? NativeLockFile.LOCKFILE_FAIL_IMMEDIATELY : 0), reserved: 0, countLow: uint.MaxValue, countHigh: uint.MaxValue, ref overlapped); return(!hasHandle ? null : new FileLock(fileLock)); } catch (AbandonedMutexException) { return(new FileLock(fileLock)); }
/// <summary> /// Releases the file lock. /// </summary> public void Dispose() { if (lockFile is not null) { var overlapped = new NativeOverlapped(); NativeLockFile.UnlockFileEx(lockFile.SafeFileHandle, 0, uint.MaxValue, uint.MaxValue, ref overlapped); lockFile.Dispose(); // Try to delete the file // Ideally we would use FileOptions.DeleteOnClose, but it doesn't seem to work well with FileShare for second instance try { File.Delete(lockFile.Name); } catch { } lockFile = null; } }
/// <summary> /// Tries to take ownership of the file lock within a given delay. /// </summary> /// <param name="name">A unique name identifying the file lock.</param> /// <param name="millisecondsTimeout">The maximum delay to wait before returning, in milliseconds.</param> /// <returns>A new instance of <see cref="FileLock"/> if the ownership could be taken, <c>null</c> otherwise.</returns> /// <remarks> /// The returned <see cref="FileLock"/> must be disposed to release the file lock. /// Calling this method with 0 for <see paramref="millisecondsTimeout"/> is equivalent to call <see cref="TryLock"/>. /// Calling this method with a negative value for <see paramref="millisecondsTimeout"/> is equivalent to call <see cref="Wait(string)"/>. /// </remarks> public static FileLock Wait(string name, int millisecondsTimeout) { var fileLock = BuildFileLock(name); try { if (millisecondsTimeout != 0 && millisecondsTimeout != -1) { throw new NotImplementedException("GlobalMutex.Wait() is implemented only for millisecondsTimeout 0 or -1"); } var overlapped = new NativeOverlapped(); bool hasHandle = NativeLockFile.LockFileEx(fileLock.SafeFileHandle, NativeLockFile.LOCKFILE_EXCLUSIVE_LOCK | (millisecondsTimeout == 0 ? NativeLockFile.LOCKFILE_FAIL_IMMEDIATELY : 0), 0, uint.MaxValue, uint.MaxValue, ref overlapped); return(hasHandle == false ? null : new FileLock(fileLock)); } catch (AbandonedMutexException) { return(new FileLock(fileLock)); } }