2012-10-02 53 views
31

私は複数のクライアントからアクセスできる共有リソース(Motionシステム)を持っているアプリケーションを持っています。私は、移動中にシステムへのアクセスを必要とする個別の操作を持っており、同時に競合する操作が要求されている場合は「ビジー」例外をスローする必要があります。また、他のアクションが散在している、いくつかのオペレーションの実行のためにモーションシステムへの排他的アクセスを取得する必要のあるシーケンサを持っています。シーケンス全体で、他のクライアントは操作を実行できません。async/awaitによるリソースロック

これまでスレッドアフィニティを使用してスレッドに排他アクセスを要求し、操作に対応するブロッキング呼び出しを実行できるようになってきました。スレッドはアクセス権を持っていますが、ほかのスレッドはリソースを使用できません。私が今問題にしているのは、よりシンプルなシーケンサーの実装を可能にするために、私はasync/awaitパターンを使用して自分のシステムを実装する方向に動いたことです。問題は、シーケンサーが常に同じスレッドで実行されているわけではないことです。アクティブなスレッドはコールバックの過程で変更される可能性があるため、実行中の操作を維持するために有効なコンテキストにいるかどうかを判断することはもはや容易ではありません。注意すべき点の1つは、オペレーションそのものがawaitsで構成されていることです。これは、シーケンスと個々のオペレーションが複数のスレッドにまたがることを意味します。

私の質問:誰かが、非同期/待機によるスレッド切り替えの存在下で排他的アクセスを獲得することに対処する良いパターンを知っていますか?参考のため

、私が考えられてきたいくつかのこと:

  1. 私はマーシャルは、すべてのシーケンサーはバック単一スレッドへのシーケンスの期間呼び出すカスタムのSynchronizationContextを作成することができます。これにより、既存のスレッドアフィニティアクセス管理コードを再利用できるという利点があります。欠点は、シーケンスまたはオペレーションのいずれかを行うたびにスレッドを専用にする必要があることです(オペレーションは複数のスレッドにまたがる可能性があるため)。

  2. Operationメソッドに渡す有効なアクセストークンを作成して、獲得アクセス。これには、トークンパラメータを使用してメソッドを拡張することの欠点があります。

  3. (2)のアクセストークンアプローチを使用しますが、オペレーションインターフェイス用の重複したインターフェイス実装を作成して、 'baked-in'トークンでラッパーをインスタンス化できるようにします。これはいくつかの醜いグルーコードを作成しますが、各メソッドにトークンを渡す必要がなくなるようにシーケンサーコードをクリーンアップします。

答えて

22

私の質問:誰が原因の非同期/待つにスレッド切り替えの存在下での排他的アクセスを取得するに対処するための良いパターンを知っていますか?

はい、AsyncLockを使用できます。これは、AsyncEx libraryの一部としても利用できます。 「TryLock」のような操作をしたい場合は、独自のプリミティブを作成する必要があります。

安全性チェックの機能が失われます。現在実行中のスレッドに特定のAsyncLockがあるかどうかを確認する方法はありません。

その他のオプションは、ConcurrentExclusiveSchedulerPair(私はhereについてのブログ)またはTPL Dataflowです。

+0

私は参考にした読解の答えとしてこれをマークします。私は最終的に、アクセスチェックを含むインターフェイスのプロキシを作成しました。私はそれが生きている間、他のプロキシインスタンスがシステムを使用するのを防ぐ特別な使い捨ての「排他的アクセス」プロキシを渡すことができます。 –

関連する問題