我有一个用Delphi编写的命令行工具,其工作是在XML文件中插入一个节点,然后立即退出。我需要使工具的几个实例同时执行,并将节点插入到同一个XML中。
为了实现这个目的,我引入了一个简单的文件“mutex” - 该工具在写入XML之前创建一个临时文件,然后在完成witing之后删除临时文件。因此,如果执行另一个实例,它会检查是否存在此临时文件,并等待它被删除。然后它再次创建临时文件,写入XML并删除临时文件。
问题是只有当2-3个实例尝试同时写入XML文件时才能正常工作。当有更多实例时 - 其中一些实例只是永远等待,并且永远不会将节点附加到XML中。
是否有更好的方法可以使大量实例同时运行并写入XML?
答案 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。