5

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

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

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

有没有更好的方法让它与同时运行和写入 XML 的大量实例一起工作?

4

5 回答 5

6

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

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

于 2008-09-19T14:28:23.050 回答
4

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

2 - 编写一个简单的应用程序来监视该文件,并将更改应用到 XML 文件

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

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

于 2008-09-19T12:19:09.163 回答
2

TXMLDocument 已经防止多个实例同时写入同一个文件。所以我猜你的问题的真正意思是,“我怎样才能打开一个 XML 文档进行阅读,防止其他实例在我阅读它时写入该文档,然后在允许其他实例之前写入该文档做同样的事?”

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

显然,如果另一个实例当前正在读取/写入文件,则打开文件可能会失败。所以你需要处理这个并稍后重试。

于 2008-09-19T12:24:34.813 回答
1

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

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

于 2008-09-19T14:18:08.630 回答
0

这个答案

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

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

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

于 2011-12-18T13:06:40.983 回答