原来只是打算实现一个进程互斥的功能,而.NET似乎没有内置,所以决定调Windows API自己写。原来简单的几句代码,加上了Exception Handling和Dispose Pattern后,居然搞出了近一百行代码,还没怎么写注释。
/// <summary>
/// Process level simple mutex class. By Sunmast.
/// </summary>
/// <remarks>
/// Always avoid duplicate mutex names.
/// </remarks>
class ProcessMutex : IDisposable
{
[DllImport("Kernel32.dll")]
static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);
[DllImport("Kernel32.dll")]
static extern bool ReleaseMutex(IntPtr hMutex);
[DllImport("Kernel32.dll")]
static extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
const uint WAIT_ABANDONED = 0x00000080;
const uint WAIT_OBJECT_0 = 0x00000000;
const uint WAIT_TIMEOUT = 0x00000102;
const uint WAIT_FAILED = 0xFFFFFFFF;
const int MAX_PATH = 260;
IntPtr hMutex;
bool disposed;
public ProcessMutex(string mutexName)
: this(mutexName, int.MaxValue)
{
}
public ProcessMutex(string mutexName, int timeout)
{
if (mutexName == null)
{
throw new ArgumentNullException("mutexName");
}
if (mutexName.Length > MAX_PATH)
{
throw new PathTooLongException("The name is limited to MAX_PATH characters.");
}
hMutex = CreateMutex(IntPtr.Zero, false, mutexName);
if (hMutex == IntPtr.Zero)
{
throw new InvalidOperationException("Mutex creation failed.");
}
uint waitResult = WaitForSingleObject(hMutex, timeout);
switch (waitResult)
{
case WAIT_TIMEOUT:
throw new TimeoutException("Cannot get mutex ownership due to time-out.");
case WAIT_OBJECT_0:
break;
case WAIT_ABANDONED:
throw new InvalidOperationException(
"The specified object is a mutex object that was not released by the " +
"thread that owned the mutex object before the owning thread terminated.");
case WAIT_FAILED:
throw new InvalidOperationException("Function failue.");
default:
break;
}
}
~ProcessMutex()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Nothing to do.
}
ReleaseMutex(hMutex);
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
其用法有点类似C#的lock关键字,可以定义一个scope,例:
using (new ProcessMutex("MUTEX_TEST"))
{
Console.WriteLine("Wait for ENTER key pressed.");
Console.ReadLine();
}
看来白忙了
,.NET已经内置了这个功能了。原来一直以为所有的WaitHandle都是线程级别的...