分享
 
 
 

如何使.NET程序只运行单一实例

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

有时你会想只运行一个程序首次运行时的实例,有些时候则可能只需要运行最新的那个实例。以下是这两种实现这两种方法的例子。

你如何才能确保只有一个.NET的程序运行在你的机器上呢?多任务操作系统在很多方面都很有用,但是有时你只需要在某一时间内运行一个实例,例如,如果程序需要使用很多的资源或者需要排它地存取某一个资源。在这种情况下,你可能想确认当另一个实例启动时,它会检查是否有另一个实例正在运行。如果是,则将自身关闭。本文中,我会告诉大家如何去实现它,还有在相关的情况下如何只允许最新的程序实例运行。请在以下地址下载程序源码ftp://ftp.wdj.com/pub/webzip/newsletters/20030815dnn.zip

最简单的方法是使用mutex对像。例如,在以下的代码中,Form的构造函数中创建了一个mutex对象,然后试着去存取它。如果WaitOne()返回true,那么当前线程就已经拥有了mutex,如果返回false则mutex已经被另一个线程所拥有。

using System;

using System.Windows.Forms;

using System.Threading;

class App : Form

{

Mutex mutex;

App()

{

Text = "Single Instance!";

mutex = new Mutex(false, "SINGLE_INSTANCE_MUTEX");

if (!mutex.WaitOne(0, false))

{

mutex.Close();

mutex = null;

}

}

protected override void Dispose(bool disposing)

{

if (disposing)

mutex.ReleaseMutex();

base.Dispose(disposing);

}

static void Main()

{

App app = new App();

if (app.mutex != null) Application.Run(app);

else MessageBox.Show("Instance already running");

}

}

在以上代码中,方法Dispose()并不严格需要,这是因为当程序结束时,垃圾回收器将会dispose并且release mutex对象。但是我仍然添加了它,这是因为Form需要一段很长的时间来释放(dispose),并且另一个窗体(Form)的实例将会启动。

这种方法只允许第一个进程实例运行。但如果你只想运行最新的那个实例时怎么办呢?就是说如果我启动了一个新的进程实例,而且之前已经有一个实例正在运行中,那么我们需要停止之前的那个线程。例如屏保的显示属性对话框。这个对话框显示一个小的预览窗口,当用用户点击预览按钮时,另一个屏保程序实例(instance)就会启动并全屏显示。当全屏实例停止时(例如你移动了鼠标),另一个屏保实例就会开始在小的预览窗口中开始运行。很明显,当全屏实例开始,这个预览的屏保窗口进程就要结束。

一种实现的方法是为每一个实例去存取一个命名的事件核心对象(named event kernel object),如果事件对象没有被触发(nonsignaled),那么此实例就继续运行;如果事件被触发则程序实例会结束。应用程序可以周期性地测试事件去看是否它已经被触发。当一个新的实例启动,它就会设置事件(去关闭其它任何实例)然后重设事件以使它可以继续运行。这种方案除了一个小问题外运行良好:.NETFramework不会允许你命名一个核心事件(kernel event)。以下是一个实现的类

public class NamedEventHelper

{

[DllImport("kernel32")]

static extern uint CreateEvent(

uint sec, bool manualReset, bool initialState, string name);

static IntPtr CreateEvent(bool manualReset, bool initialState, string name)

{

return new IntPtr(CreateEvent(0, manualReset, initialState, name));

}

[DllImport("kernel32")]

static extern bool CloseHandle(IntPtr handle);

public static ManualResetEvent CreateNamedEvent(

bool initialState, string name)

{

ManualResetEvent mre = new ManualResetEvent(false);

CloseHandle(mre.Handle);

mre.Handle = CreateEvent(true, initialState, name);

return mre;

}

}

以上的代码中,静态(static)方法CreateNamedEvent()创建了一个ManualResetEvent对象,并释放了当前的(underlying)Win32句柄(handle)。然后再创建一个命名事件(named event)并且使用此新事件的句柄初始化了ManualResetEvent对象。此事件对象就能被用于两个应用程序间的通信。

这种方案的弱点是一个应用程序一定要看它是否已经结束。一种解决方法是运行一个后台线程去管理事件

ManualResetEvent mre;

mre = NamedEventHelper.CreateNamedEvent(false, "LAST_INSTANCE_ONLY");

// Stop the other instances

mre.Set();

// Reset the event so that we can run

mre.Reset();

// Create a monitor thread

Thread t = new Thread(new ThreadStart(Monitor));

// Make sure that this thread cannot keep the app alive

t.IsBackground = true;

t.Start();

//The Monitor() method looks like this:

void Monitor()

{

mre.WaitOne();

Application.Exit();

}

如果程序有一个窗体,那么另一种方法就是告诉其它窗口去关闭这个新的程序实例。如果这是一个Win32应用程序,那么此程序可以简单地通过调用FindWindowsEx(),并传入一个特定的窗口类参数,然后发送WM_CLOSE消息。但是你不能对Windows Form这样做

,因为大多数窗体(Forms)都有相同的类名,正如我在上一封newsletter是所说的。在下一个newsletter中,我会解释另一种方法去解决这类问题。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有