2

因此,我能够在 Windows 上强制执行我的应用程序的单个实例,如下所示。

[STAThread]
class method Program.Main(args: array of string);
begin
  var mutex := new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
  if mutex.WaitOne(Timespan.Zero, true) then
  begin
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.ThreadException += OnThreadException;
    lMainForm := new MainForm;
    lMainForm.ShowInTaskbar := true;
    lMainForm.Visible := false;

    Application.Run(lMainForm);
  end
  else
    MessageBox.Show("Another copy running!!!");
end;

但是,在单声道下在 Linux 上运行相同的应用程序,此代码根本不起作用。我能够运行多个副本。我不知道这是否与我在终端上启动应用程序(如mono MyPro.exe. 如果这是问题所在,是否需要在执行命令行之前传递一些值。

提前致谢,

4

3 回答 3

3

您可能需要使用 MONO_ENABLE_SHM 环境变量启用共享句柄:

MONO_ENABLE_SHM=1 mono MyPro.exe
于 2012-11-06T15:18:48.017 回答
3

您需要像 Adrian Faciu 提到的那样在单声道中启用共享内存才能使您的方法正常工作,但这不是最好的方法(首先默认情况下禁用它是有原因的,即使我现在不记得确切原因) .

我过去使用过两种解决方案:

  • 基于文件的锁。创建一个已知文件,将 pid 写入该文件。在您的应用程序启动时检查文件是否存在,如果存在,则读取 pid 并检查是否有任何正在运行的进程使用该 pid(以便它可以从崩溃中恢复)。并在退出时删除文件(在首先创建它的实例中)。缺点是如果几乎同时启动多个实例,则启动时会出现竞争条件。您可以通过文件锁定来改进这一点,但您可能必须使用 P/Invokes 在 Linux 上执行正确的文件锁定(我不完全确定托管 API 会按照您的预期进行)。

  • 基于袜子的锁。打开一个已知端口。上面的优点是您不需要进行任何清理并且没有竞争条件。缺点是您需要一个固定/已知端口,而其他一些程序可能碰巧同时使用该确切端口。

于 2012-11-06T22:35:27.580 回答
1

阿德里安的解决方案对我有用(tm)。疯狂的猜测:你在两个调用中都需要 MONO_ENABLE_SHM吗?

于 2012-11-06T16:57:42.217 回答