質問
F#でCCRフレームワークのポートの概念を実装したい(CCRは.NET 4.0で公式にサポートされていないため)。私はそれを使うことができることを知っています MailBoxProcessor これを行うためのF#のクラス。これはシンプルに完全に機能します 受け取る arbitersしかし、私はの概念が必要です 間を空ける Arbiter、つまり、どのメッセージが排他的に処理され、どのメッセージが同時に処理されるかを制御したいと思います。これまでのところ、これをF#に実装することはわからず、ご協力に感謝します。
解決
私はCCRにあまり精通していませんが、私は答えようとします - 私の理解は インターリーブアービター 少しのように振る舞います ReaderWriterLock
. 。つまり、並行して実行できる操作(読み取り)と排他的な操作(書き込み)を指定することができます。
次のエージェントは、それを実装する1つの方法です(テストされていませんが、チェックを入力:-))。エージェントは、公共の使用を目的とした2つの操作を公開します。最後のものは内部です:
type Message<'T> =
| PerformReadOperation of ('T -> Async<unit>)
| PerformWriteOperation of ('T -> Async<'T>)
| ReadOperationCompleted
エージェントを送信します
PerformReadOperation
, 、状態を使用して(1回)、おそらく他の読み取り操作と並行して実行する必要がある操作を提供しています。エージェントを送信します
PerformWriteOperation
, 、新しい状態を計算し、すべての読み取り操作が完了した後に実行する必要がある操作を提供しています。 (不変の状態で作業している場合、それは物事をより簡単にするでしょう - 読者が完了するまで待つ必要はありません!しかし、以下の実装は待機を実装します)。
エージェントは、いくつかの初期状態で始まります。
let initial = // initial state
エージェントの残りの部分は、2つのループを使用して実装されます。
let interleaver = MailboxProcessor.Start(fun mbox ->
// Asynchronously wait until all read operations complete
let rec waitUntilReadsComplete reads =
if reads = 0 then async { return () }
else mbox.Scan(fun msg ->
match msg with
| ReadOperationCompleted -> Some(waitUntilReadsComplete (reads - 1))
| _ -> None)
let rec readingLoop state reads = async {
let! msg = mbox.Receive()
match msg with
| ReadOperationCompleted ->
// Some read operation completed - decrement counter
return! readingLoop state (reads - 1)
| PerformWriteOperation(op) ->
do! waitUntilReadsComplete reads
let! newState = op state
return! readingLoop newState 0
| PerformReadOperation(op) ->
// Start the operation in background & increment counter
async { do! op state
mbox.Post(ReadOperationCompleted) }
|> Async.Start
return! readingLoop state (reads + 1) }
readingLoop initial 0)
他のヒント
Tomasが提案されたソリューションに追加するために、メールボックスの消費者に「ReadOperationCompleted」メッセージを公開したくない場合に備えて(このメッセージは内部であり、現在の実装はメールボックスの消費者が送信できます)メインのメールボックスプロセッサ関数内には、2つのメッセージを受け入れるメインのメールボックスプロセッサ関数内に作成できます。読み取りcompletedとwaitforreadcompleted(これは、メインメールボックスによってpostandasyncreplyで使用されます)は、このメッセージへの応答がすべて読み取られた場合にのみ来ます。操作が完了しました。また、「読み取り」で表される「読み取り」カウントは、この状態がこの内部メールボックスによってカプセル化されるため、この新しい内部メールボックスに移動されます。