C#应用程序在默认情况下可以被多次启动的实例。但有些应用程序需要保证只能启动一个实例,可以通过以下两种方式来实现该需求。
方法一:使用 Mutex 对象控制应用程序启动
Mutex 对象是一种操作系统原语,可控制多个进程或线程执行特定代码的互斥访问。应用程序可以使用 Mutex
类来创建一个已命名的 Mutex 对象,并在不同进程之间共享该对象。当有一个进程创建了该 Mutex 对象时,其他试图创建同名 Mutex 对象的进程会停顿等待,直到前面创建的进程释放了 Mutex 对象。
因此,我们可以通过尝试创建已命名的 Mutex 对象,根据返回值来判断应用程序是否已经运行。若对象已存在,则表明应用程序已运行;否则,表明应用程序未运行。
下面是相关代码示例:
using System.Threading;
static class Program
{
static Mutex mutex = new Mutex(true, "MyAppMutex");
[STAThread]
static void Main()
{
if (!mutex.WaitOne(TimeSpan.Zero, true))
{
MessageBox.Show("只能运行一个实例");
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
mutex.ReleaseMutex();
}
}
在上面的代码中,我们创建了全局唯一的 Mutex 对象 “MyAppMutex”,并使用 WaitOne()
方法尝试等待 Mutex 的所有权,等待时间为0,表示立即返回。如果该 Mutex 对象已在其他进程中被持有,则当前进程等待 TimeOut 时间之后再次检查 Mutex 对象的状态,直到 Mutex 对象被释放。在应用程序结束时,我们需要调用 ReleaseMutex()
方法释放 Mutex 对象所有权。
方法二:通过 WCF 端口检查应用程序启动
通过创建一个 WCF 端口并绑定到后台线程中进行监听的方式,我们可以实现检测是否已经有相同的客户端连接来实现禁止应用程序多次启动的效果。具体的代码示例如下:
using System.ServiceModel;
static class Program
{
static readonly string UniqueAddress = string.Format("net.pipe://localhost/{0}/", typeof(MainForm).GUID);
[STAThread]
static void Main()
{
using (var channelFactory = new ChannelFactory<ISingleInstance>(CreateBinding(), CreateEndpoint()))
{
bool createdNew;
var mutex = new Mutex(true, typeof(MainForm).GUID.ToString(), out createdNew);
if (!createdNew)
{
channelFactory.CreateChannel().Ping();
return;
}
try
{
mutex.ReleaseMutex();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(channelFactory));
}
finally
{
mutex.Close();
}
}
}
private static Binding CreateBinding()
{
return new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
}
private static EndpointAddress CreateEndpoint()
{
return new EndpointAddress(UniqueAddress);
}
[ServiceContract]
public interface ISingleInstance
{
[OperationContract(IsOneWay = true)]
void Ping();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true)]
public class SingleInstance : ISingleInstance
{
public void Ping() { return; }
}
}
在上面的代码中,创建了一个 GUID 并使用互斥对象来保证只有一个线程实例化该 WCF 端口服务。如果已有一个应用程序实例在运行,当前应用程序将使用 WCF 端口发送 Ping 请求给现有实例,然后直接结束。
在第一个实例关闭前,如果再次试图创建实例,将直接退出。如果该端口未被监听,则当前实例则会完成启动。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 禁止应用程序多次启动的实例 - Python技术站