【问题标题】:How to enforce single instance of an application under mono?如何在单声道下强制执行应用程序的单个实例?
【发布时间】:2012-11-06 15:14:27
【问题描述】:

因此,我可以在 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)有关。如果这是问题所在,是否需要在执行命令行之前传递一些值。

提前致谢,

【问题讨论】:

    标签: mono delphi-prism single-instance oxygene


    【解决方案1】:

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

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

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

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

    【讨论】:

    • Rolf Bjarne Kvinge,我看过基于文件的锁。但是,它有一个主要缺点。如果您在没有管理员权限(如删除文件)的用户帐户上运行程序怎么办?大多数情况下,您使用的是用户帐户而不是管理员帐户。在实现了基于文件的锁之后,我遇到了这个问题。我的程序可以创建文件,但在正常关闭时无法删除。
    • @digitalanalog:如果您需要锁定跨用户帐户,则需要将文件放在所有用户帐户都具有读/写访问权限的位置(想到 C:\System\Temp,但是可能是其他/更好的位置)。
    • Rolf,可能有一种更直接的方法可以通过托管代码执行此操作,但到目前为止我还没有发现它。所以,我确实发现基于文件的锁很容易实现。我能够弄清楚为什么它没有删除我的 Linux 系统上的文件。现在它按预期工作。感谢您的帮助。
    【解决方案2】:

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

    MONO_ENABLE_SHM=1 mono MyPro.exe
    

    【讨论】:

    • 阿德里安,我确实尝试了你的建议,但没有奏效。正如我所说,我必须打开两个不同的终端才能启动我的程序的两个不同副本。所以,也许这就是你的建议没有奏效的原因。
    【解决方案3】:

    Adrian 的解决方案适用于我(tm)。 大胆猜测:两个调用中是否需要 MONO_ENABLE_SHM?

    【讨论】:

    • 或者如果一切都失败了,考虑“unix方式”,即在一个公共目录中拥有锁定文件
    • loreb,我不确定你是否确实需要它,但无论如何我都尝试过这两种调用。尽管如此,它还是没有用。我什至想可能是因为它都是大写字母并尝试使用所有小写字母。再次,它没有工作。我不知道这是否有助于更清楚地了解这个问题,但我正在尝试在单声道下的 PCLinuxOS 上执行此操作。
    • @Earlz,这就是我现在正在查看的其他人在论坛和在线留言板上的建议。
    • Debian x86_64 这里 fwiw,我的互斥锁被命名为“mymutex”。
    • @Earlz,如果我可以问你,你是如何在 Linux 上启动程序的 - 直接通过右键单击可执行文件本身或从终端启动。显然,我在终端上使用 MONO_ENABLE_SHM 选项,发现它正在被单声道识别。因为当我拼写错误时,mono 表示它是无法识别的命令。如果是这样,那么为什么程序不会按预期运行。请给我一步一步的指导,告诉我你是如何测试这个单声道选项的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-04-30
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    相关资源
    最近更新 更多