代码之家  ›  专栏  ›  技术社区  ›  m_pGladiator

如何使用Delphi管理EXE的多个实例对XML文件的并发输入/输出访问。

  •  5
  • m_pGladiator  · 技术社区  · 17 年前

    我有一个用Delphi编写的命令行工具,它的任务是在XML文件中插入一个节点,然后立即退出。我需要使该工具的多个实例能够同时执行,并将节点插入到同一个XML中。

    为了达到这个目的,我引入了一个简单的文件“互斥”——该工具在写入XML之前创建一个临时文件,然后在写入完成后删除该临时文件。因此,如果执行另一个实例,它会检查是否存在此临时文件,并等待删除。然后,它再次创建临时文件,写入XML并删除临时文件。

    问题是,只有当2-3个实例尝试同时写入XML文件时,这才能正常工作。当有更多实例时,其中一些实例只是永远等待,从不将节点附加到XML中。

    是否有更好的方法使其能够同时处理大量运行和写入XML的实例?

    5 回复  |  直到 13 年前
        1
  •  6
  •   Barry Kelly    17 年前

    命名信号量或互斥量可以在单台机器上为您完成此操作。例如,使用SyncObjs中的TMutex,并使用一个接受name参数的构造函数。如果在所有应用程序中使用相同的名称,它们将通过相同的内核互斥体进行同步。使用TMutex。获取访问权限,以及TMutex。完成后释放,在try/finally块中保护。

    使用TMutex。创建具有InitialOwner参数的重载,但为此指定False(当然,除非您想立即获取互斥体)。这种重载在幕后调用CreateMutex。查看SyncObjs的源代码和文档 CreateMutex 更多细节。

        2
  •  4
  •   JosephStyons    17 年前

    1-设置一个记录待处理更改的文件(它将像队列一样工作)

    2-编写一个简单的应用程序来查看该文件,并将更改应用于XML文件

    3-修改当前的命令行工具,将他们的更改请求附加到“待定更改”文件中

    现在,只有一个应用程序需要接触最终的XML文件。

        3
  •  2
  •   Craig Stuntz    17 年前

    TXMLDocument已经防止多个实例同时写入同一文件。所以我猜你的问题真正的意思是,“我如何打开一个XML文档进行阅读, 在我阅读文档时,防止其他实例写入文档 ,然后在允许其他实例执行相同操作之前写入文档?"

    在这种情况下,您应该自己处理打开和关闭文件,而不是让TXMLDocument为您完成。使用TFileStream打开具有独占读写锁和XMLDocument的文件。LoadFromStream而不是LoadFromFile。重置流后,使用SaveToStream保存文档。位置为0。使用try/finally以确保在完成流后关闭流。由于您以独占方式锁定了文件,因此不再需要临时文件或任何其他类型的互斥体。

    显然,如果另一个实例当前正在读/写文件,打开文件可能会失败。因此,您需要处理此问题,稍后重试。

        4
  •  1
  •   skamradt    17 年前

    请记住,每次需要添加节点时,都必须重新加载和重新解析整个文档。根据XML文档的大小和要保存的数据,这可能不是传输数据的最有效方法。

    写入单独文件的方法是一种有趣的解决方案,可以考虑让您的“多实例”应用程序写入唯一的XML文件,然后使用FindFirst循环将这些文件加载到具有单独程序的主文档中。这样,您就可以在不对现有程序进行任何重大更改的情况下,保持xml结构的完整性。

        5
  •  0
  •   Community CDub    8 年前

    来自 this answer :

    在Windows上,如果您可以控制这两个程序,这是可能的。 LockFileEx。对于读取,打开锁文件上的共享锁。对于写入, 在锁文件上打开独占锁。锁定在Windows中很奇怪, 所以我建议为此使用单独的锁文件。

    (“两个程序”不适用于您的情况,因为它是同一个程序,只是在多个实例中运行。)

    旁注/我是如何找到这个答案的:Java日志库 logback 使用特定于平台的文件锁定API(通过NIO)来实现 prudent mode “多个进程可以登录到同一个文件而不会损坏它——这是Delphi RTL文件操作无法实现的。