【问题标题】:How to check if there are other application instances running如何检查是否有其他应用程序实例正在运行
【发布时间】:2013-04-24 18:48:09
【问题描述】:

我用 C# 编写了一个应用程序,它放置在我们的服务器上。 当有人需要使用它时,应用程序会直接从服务器启动,从我们局域网中任何连接的 PC 启动。

有什么简单的方法可以检查有多少实例正在运行?或者更确切地说,如果有任何其他实例而不是由我启动的实例?


编辑:

这不是提供的帖子的副本,因为我不想确保只有一个实例在运行(如“不要同时运行超过 1 个应用程序”),而只是检查,是否有人在运行它(在正常情况下,它必须同时在多台 PC 上运行)

【问题讨论】:

  • 启动为“在服务器上运行”或“当文件位于服务器上时在用户计算机上本地运行”?
  • 此应用在每台 PC 本地运行,但可执行文件在服务器上。所以第二个选项。
  • 可以在服务启动时创建一个全局命名的互斥锁,在服务关闭时释放。然后任何其他进程也可以尝试创建一个同名的全局互斥锁,看看它是否创建了它。请参阅this thread 了解打开互斥锁的正确方法。

标签: c# .net


【解决方案1】:

没有简单的方法可以从相同的二进制文件中知道程序的实例在某些机器上运行 - 您的程序需要以某种方式将“我正在运行”报告到某个共享位置,而不是检查是否有其他实例正在运行。

如果您只需要检查单个实例,则可以从同一位置打开文件,如果多个实例尝试打开它,它将失败。

用于计算实例的共享位置的几个选项:

  • 用机器名更新一些文件
  • 一些要 ping 的 Web 服务/站点
  • 共享数据库

请注意,这也意味着如果程序终止,则共享位置可能不会报告有关此特定实例已完成的报告。

【讨论】:

    【解决方案2】:

    有几种方法可以做,例如,使用套接字、数据库。一种最简单的方法(但不那么安全)可能是使用文件来记录实例的数量,您可能需要改进它。

    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 处理程序。

    【讨论】:

      【解决方案3】:

      一般来说,为了只允许应用程序的 N 个并发实例,您可以使用命名信号量,因为它们在整个系统中都是可见的。

      当您启动应用程序时,尝试创建一个名为Semaphore 的参数指定允许的实例数。如果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() 的变体,具体取决于您的应用需求。

      编辑:哎呀,刚刚注意到您实际上不需要这个,而是验证在不同机器上运行的实例 - 如果没有向服务器报告的机制,这会更难。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多