咨询区
- C. Dragon 76:
在 .NET 中是否有比较好的方法可以阻止一个 application 被同时开启了多个实例?如果没有好的办法,那么只能退其次,给每个 application 配一些操作规范。
回答区
- ImJustPondering:
我总结有两种解法。
- 使用 Meutx。
[STAThread]
static void Main()
{
using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
Application.Run(new Form1());
}
}
private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
关于 Mutex
更多资料,可参考:http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
- 使用 Process
可以迭代进程列表,判断是否已经存在该进程名即可,参考如下代码:
using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
int procCount = 0;
foreach (Process pp in Process.GetProcesses())
{
try
{
if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
{
procCount++;
if(procCount > 1) {
Application.Exit();
return;
}
}
}
catch { }
}
Application.Run(new Form1());
}
- Tono Nam:
其实可以仿 linux 上生成进程文件的方式,所以要做的就是在程序启动后,在某一个文件中写入一个默认的 uniqueid 值,参考如下代码:
public static void PreventMultipleInstance(string applicationId)
{
// Under Windows this is:
// C:\Users\SomeUser\AppData\Local\Temp\
// Linux this is:
// /tmp/
var temporaryDirectory = Path.GetTempPath();
// Application ID (Make sure this guid is different accross your different applications!
var applicationGuid = applicationId + ".process-lock";
// file that will serve as our lock
var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);
try
{
// Prevents other processes from reading from or writing to this file
var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_InstanceLock.Lock(0, 0);
MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);
// todo investigate why we need a reference to file stream. Without this GC releases the lock!
System.Timers.Timer t = new System.Timers.Timer()
{
Interval = 500000,
Enabled = true,
};
t.Elapsed += (a, b) =>
{
try
{
_InstanceLock.Lock(0, 0);
}
catch
{
MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
}
};
t.Start();
}
catch
{
// Terminate application because another instance with this ID is running
Environment.Exit(102534);
}
}
点评区
这个需求本质上和防重复登录时一样的,大概三种吧:
- 机器内作用域:
Metux,Process 是一个好办法。
- 跨机器或局域网作用域:
生成 PID 文件是一个好办法。
- 局域网,广域网:
可用 redis,zookeeper 之类的全局锁机制。
—
经典回顾