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

时间:2008-09-19 12:01:41

标签: xml delphi mutex

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

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

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

是否有更好的方法可以使大量实例同时运行并写入XML?

5 个答案:

答案 0 :(得分:6)

命名信号量或互斥量可以在一台机器上为您完成此操作。使用例如来自SyncObjs的TMutex,并使用其中一个带名称参数的构造函数。如果在所有应用程序中使用相同的名称,它们将在同一内核互斥锁上进行同步。使用TMutex.Acquire访问,以及TMutex。完成后,请在try / finally块中保护。

使用具有InitialOwner参数的TMutex.Create重载,但为此指定False(当然,除非您想立即获取互斥锁)。此重载在后台调用CreateMutex。查看SyncObjs的源代码和CreateMutex的文档以获取更多详细信息。

答案 1 :(得分:4)

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

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

3 - 修改当前命令行工具,将其更改请求附加到“待处理更改”文件

现在只有一个应用程序必须触及最终的XML文件。

答案 2 :(得分:2)

TXMLDocument已经阻止多个实例同时写入同一个文件。所以我猜你的问题的真正含义是,“如何打开XML文档进行阅读,防止其他实例在我阅读时写入文档,然后写入允许其他实例做同样的事情之前的文件?“

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

来自this answer

  

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

('两个程序'dos在你的情况下不适用于它是同一个程序,只是在多个实例中运行。)

附注/我如何找到这个答案:Java日志库logback使用特定于平台的文件锁定API(通过NIO)来实现“prudent mode”,其中多个进程可以登录到同一个文件没有破坏它 - 使用Delphi RTL文件操作无法实现iiuc。