使用 Mutex 创建 单例应用程序

 

  Mutex是从WaitHandle派生的类,保证了多个线程在某个资源或代码块上互相排斥。Mutex定义如下:

public sealed class Mutex : WaitHandle { public Mutex(); public Mutex(bool initiallyOwned); public Mutex(bool initiallyOwned,string name); public Mutex(bool initiallyOwned,string name,out bool createdNew); public static Mutex OpenExisting(string name); public void ReleaseMutex(); }

Mutex的实例为句柄分配了两个逻辑意义:被占有和不被占有,也就是在任何时候都只能被一个线程所拥有。当一个线程试图申请Mutex,而它此时被其它线程占有,则该线程被阻塞,直到Mutex的所有者调用ReleaseMutex()让出所有权。

 

从定义中可以看出,Mutex的构造函数有多种重载,默认构造函数创建的Mutex为不占用状态,本次着重介绍第3种重载。

参数含义如下:

bool initiallyOwned : 接受布尔值,为true表示创建的Mutex对象所有权归创建线程所有,反之亦然;

string name : 为Mutex实例对象指定一个唯一的名称,称为命名的Mutex,稍后将会使用到;

 

上文提到,当一个线程试图访问已被占有的Mutex时,会阻塞当前线程的执行,这时,可使用方法WaitOne()等待,WaitOne也有很多重载版本,因为本文着重介绍应用程序的单例模式,所以只使用到了其中一个版本,定义如下:

WaitOne(Int32 , bool exitContext) 阻止当前线程,直到当前 Mutex可用,同时使用 32 位带符号整数测量时间间隔。

WaitOne(TimeSpan , bool exitContext)) 阻止当前线程,直到当前 Mutex可用,同时使用 TimeSpan 测量时间间隔。

bool exitContext 的说明不在本文的论述范围内。使用时将其设置为false即可;

 

下面简要提一下上文中提到的"命名的Mutex",在第3中构造函数中,允许为Mutex实例对象提供一个全局唯一的名字,默认情况下,它是没有名字的。当你为它提供一个名称后,机器上的任何线程,包括在其他应用程序域或进程中的线程都可以访问该命名的Mutex。在指定名称时,操作系统会检查是否已经有其他人创建了同名的Mutex,如果有,就给创建者线程一个本地对象来表示全域Mutex。一个命名的Mutex允许跨进程和跨应用程序域进行通信(这有点类似于IPC,当然他们是不能相提并论的!),此时,initiallyOwned应该设置为false,这是很必要的。

 

下面要进行今天的主题了(单例应用程序)

 

用过MS outlook,和网易有道词典的应该都知道,当你已经打开一个实例时,此时你又点击应用图标试图再次打开,这时,程序并没有如愿打开,而是切换到了已经存在的程序界面,这就是单例程序,程序如其名,单例,也就是单个实例。

 

下面看一段代码:

static class Program { static void Main() { SingletonApp.Run(new MyForm); } }

这段很熟悉的代码就是在创建WinForm项目的时候自动生成的,不同的是原来的Application已经改为了SingletonApp,下面是SingletonApp的定义:

public static class SingletonApp { static Mutex _mutex; public static void Run(Form MyForm) { bool first = IsFirstInstance(); if (first) { Application.ApplicationExit += OnExit; Application.Run(MyForm); } else { MessageBox.Show("另一个实例已经在运行!"); } } static bool IsFirstInstance() { Assembly ass = Assembly.GetEntryAssembly(); string name = ass.FullName; _mutex = new Mutex(false, name); bool owned = false; owned = _mutex.WaitOne(0, false); return owned; } static void OnExit(object sender, EventArgs args) { _mutex.ReleaseMutex(); _mutex.Close(); } }

当没有应用程序的其他实例在运行,窗体就会显示出来成功运行,如果已经存在该程序的实例,则会显示一条提示信息,然后退出执行。

在内部,SingletonApp使用了Application类,如果启动的是唯一的实例,它就将run的实现委托给这个类,反之,则放弃执行。

当单例程序关闭时,它必须释放Mutex的所有权,新实例才能得以执行,幸运的是,Application类提供了ApplicationExit事件,用于发出应用程序关闭的信号,SingletonApp类订阅了该事件,当单例程序退出之前将释放命名Mutex的所有权,然后关闭应用程序。

 

你可能感兴趣的:(使用 Mutex 创建 单例应用程序)