Delphi を使用して、EXE の複数のインスタンスから XML ファイルへの同時入出力アクセスを管理する方法。
質問
Delphi で書かれたコマンド ライン ツールを持っています。このツールは、XML ファイルにノードを挿入し、すぐに終了するというものです。ツールの複数のインスタンスを同時に実行し、ノードを 1 つの同じ XML に挿入できるようにする必要があります。
この目的を達成するために、私は単純なファイル「mutex」を導入しました。このツールは、XML に書き込む前に 1 つの一時ファイルを作成し、書き込みが終了した後にその一時ファイルを削除します。したがって、別のインスタンスが実行されると、この一時ファイルの存在がチェックされ、削除されるまで待機します。次に、一時ファイルを再度作成し、XML に書き込み、一時ファイルを削除します。
問題は、これが 2 ~ 3 個のインスタンスが同時に XML ファイルに書き込もうとする場合にのみ正常に機能することです。さらに多くのインスタンスがある場合、その一部は単に永久に待機し、XML にノードを追加しません。
多数のインスタンスが実行され、同時に XML に書き込まれる場合に動作させる、より良い方法はあるでしょうか?
解決
名前付きセマフォまたはミューテックスを使用すると、単一のマシン上でこれを行うことができます。使用例:SyncObjs の TMutex を使用し、名前引数を取るコンストラクターの 1 つを使用します。すべてのアプリケーションで同じ名前を使用すると、それらは同じカーネル ミューテックス上で同期されます。TMutex.Acquire を使用してアクセスし、完了したら TMutex.Release を使用して、try/finally ブロックで保護します。
InitialOwner 引数を持つ TMutex.Create オーバーロードを使用しますが、これには False を指定します (もちろん、すぐにミューテックスを取得したい場合を除きます)。このオーバーロードは、バックグラウンドで CreateMutex を呼び出します。SyncObjs のソースとドキュメントを調べてください。 ミューテックスの作成 詳細については、
他のヒント
1 - 保留中の変更を記録するファイルを設定します (キューのように機能します)。
2 - そのファイルを監視する簡単なアプリを作成し、変更を XML ファイルに適用します
3 - 現在のコマンドライン ツールを変更して、変更リクエストを「保留中の変更」ファイルに追加します。
これで、最終的な XML ファイルに触れる必要があるアプリは 1 つだけになります。
TXMLDocument は、複数のインスタンスが同じファイルに同時に書き込むことをすでに防止しています。したがって、あなたの質問の本当の意味は、「XML ドキュメントを開いて読み取るにはどうすればよいですか?」ということだと思います。 私がドキュメントを読んでいる間、他のインスタンスがドキュメントに書き込めないようにします, 他のインスタンスに同じことを許可する前に、ドキュメントに書き込みますか?」
この場合、TXMLDocument にファイルの開閉を許可するのではなく、自分でファイルの開閉を処理する必要があります。LoadFromFile の代わりに TFileStream を使用して、排他的な読み取りおよび書き込みロックと XMLDocument.LoadFromStream を使用してファイルを開きます。stream.Position を 0 にリセットした後、SaveToStream でドキュメントを保存します。ストリームが終了したときにストリームを確実に閉じるために、try/finally を使用します。ファイルを排他的にロックしているため、一時ファイルやその他の種類のミューテックスは必要なくなります。
明らかに、別のインスタンスが現在ファイルの読み取り/書き込みを行っている場合、ファイルを開くと失敗する可能性があります。したがって、これを処理して、後で再試行する必要があります。
ノードを追加する必要があるたびに、ドキュメント全体を再ロードして再解析する必要があることに注意してください。XML ドキュメントのサイズと保存するデータによっては、これがデータ転送の最も効率的な方法ではない場合があります。
別個のファイルに書き込むというアプローチは興味深い解決策です。検討すべき方法の 1 つは、「複数インスタンス」アプリに一意の XML ファイルを書き込ませ、それを FindFirst ループを使用して別個のプログラムでマスター ドキュメントに読み込むことです。こうすることで、既存のプログラムに大きな変更を加えることなく、XML 構造をほぼそのままの状態に保つことができます。
から この答え:
Windows では、両方のプログラムを制御できればこれが可能です。LockFileEx.読み取りの場合は、ロックファイルの共有ロックを開きます。書くために、ロックファイルに排他的なロックを開きます。Windowsではロックは奇妙なので、このために別のロックファイルを使用することをお勧めします。
(「両方のプログラム」は、同じプログラムであり、複数のインスタンスで実行されているだけであるため、あなたの場合には適用されません。)
補足/この答えを見つけた方法:Java ロギング ライブラリ ログバック プラットフォーム固有のファイル ロック API (NIO 経由) を使用して、慎重モード' 複数のプロセスが同じファイルを破損することなくログインできますが、これは iiuc では Delphi RTL ファイル操作では不可能です。