我用 C# 编写了一个应用程序,它放置在我们的服务器上。当有人需要使用它时,应用程序直接从服务器启动,从我们局域网中任何连接的 PC 启动。
有没有简单的方法来检查有多少实例正在运行?或者更确切地说,如果有任何其他实例而不是我开始的实例?
编辑:
这不是提供的帖子的副本,因为我不想确保只有一个实例正在运行(如“不要同时运行超过 1 个应用程序”),但只是检查一下,如果我以外的其他人正在运行它(在正常情况下,它必须在多台 PC 上同时工作)
没有简单的方法可以知道程序实例在同一二进制文件的某些机器上运行 - 您的程序需要以某种方式将“我正在运行”报告到某个共享位置,而不是检查是否有其他实例正在运行。
如果您只需要检查单个实例,则可以从同一位置打开文件,如果多个实例尝试打开它,它将失败。
共享位置计数实例的几个选项:
请注意,这也意味着如果程序终止,则共享位置中可能不会报告有关此特定实例已完成的报告。
有几种方法可以做,例如,使用套接字、数据库。一种最简单的方法(但不那么安全)可能是使用文件来记录实例的数量,您可能需要改进它。
void WriteToFile(int x, int millisecondsTimeout) {
for(; ; Thread.Sleep(millisecondsTimeout))
try {
using(var file=File.Open("instances.bin", FileMode.OpenOrCreate)) {
var bytes=new byte[sizeof(int)];
file.Read(bytes, 0, sizeof(int));
var instances=x+BitConverter.ToInt32(bytes, 0);
if(instances>-1)
file.Write(BitConverter.GetBytes(instances), 0, sizeof(int));
break;
}
}
catch(IOException ex) {
}
}
void Increment() { // invoke on program starts
WriteToFile(1, 1000);
}
void Decrement() { // invoke on program exits
WriteToFile(-1, 1000);
}
请注意,该文件"instances.bin"
应该是位于服务器上的文件。
AppDomain.CurrentDomain.UnhandledException
一旦程序意外终止,您可能还想编写一个处理程序。
通常,为了只允许应用程序的 N 个并发实例,您可以使用命名信号量,因为它们在系统中是可见的。
当您启动应用程序时,尝试使用指定允许的实例数量的参数创建一个命名信号量。如果WaitOne
失败,这意味着所有实例都在使用中,因此您退出应用程序。
这是示例代码(在我的脑海中,掩盖了一些微妙的问题,没有错误处理等)
const int MAX_INSTANCES = 2; // set desired number of concurrent instances
var s = new Semaphore(MAX_INSTANCES, MAX_INSTANCES, "unique_name_of_semaphore");
if (s.WaitOne(0)) // zero timeout - exit immediately if exhausted
{
// good, we're in, run the app
Application.Run(new Form()); // run the app - a winforms example
s.Release(); // release the semaphore
}
else
{
// oops, exhausted:
MessageBox.Show("too many instances running !!");
}
您还可以使用 Semaphore.OpenExisting() 的变体,具体取决于您的应用程序需求。
编辑:哎呀,只是注意到您实际上不需要这个,而是验证在不同机器上运行的实例 - 如果没有向服务器报告的机制,这会更难。