複数のクライアントからアクセスできる共有リソース (モーション システム) を持つアプリケーションがあります。移動中にシステムへのアクセスを必要とする個々の操作があり、競合する操作が同時に要求された場合、「ビジー」例外をスローする必要があります。また、他のアクションが散在するいくつかの操作を実行するために、モーション システムへの排他的アクセスを取得する必要があるシーケンサーもあります。シーケンス全体の間、他のクライアントは操作を実行できません。
スレッドが排他的アクセスを要求し、操作に対応するブロッキング呼び出しを実行できるように、私は伝統的にスレッド アフィニティを使用してこれにアプローチしてきました。スレッドがアクセスできる間、他のスレッドはリソースを使用できません。私が今抱えている問題は、よりクリーンなシーケンサーの実装を可能にするために、非同期/待機パターンを使用してシステムを実装する方向に進んだことです。問題は、シーケンサーが常に同じスレッドで実行されているとは限らないことです。アクティブなスレッドはコールバックの過程で変化する可能性があるため、操作を実行し続けるのに有効なコンテキストにいるかどうかを判断するのはもはや簡単ではありません。注目すべき点の 1 つは、オペレーション自体の一部が await で構成されていることです。つまり、シーケンスと個々のオペレーションの両方が複数のスレッドにまたがることができます。
私の質問: async/await によるスレッド切り替えの存在下で排他的アクセスの取得に対処するための適切なパターンを知っている人はいますか?
参考までに、私が検討したいくつかのこと:
シーケンス中のすべてのシーケンサー呼び出しを単一のスレッドにマーシャリングするカスタム SynchronizationContext を作成できます。これには、既存のスレッド アフィニティ アクセス管理コードを再利用できるという利点があります。欠点は、シーケンスまたは操作のいずれかを実行するたびにスレッド専用にする必要があることです (操作は複数のスレッドにまたがることもできるため)。
アクセス権を取得したことを証明するために Operation メソッドに渡す取得可能なアクセス トークンを作成します。これには、トークン パラメーターを使用してメソッドが肥大化するという欠点があります。
(2) のアクセス トークン アプローチを使用しますが、Operations インターフェイスのインターフェイス実装を複製して作成し、ラッパーを「焼き付けられた」トークンでインスタンス化できるようにします。これにより、醜いグルー コードが作成されますが、シーケンサー コードがクリーンアップされるため、各メソッドにトークンを渡す必要がなくなります。