次のコードを使用します。
var dispatcherQueue = new DispatcherQueue();
long totalSum = 0;
Arbiter.Activate(
dispatcherQueue,
Arbiter.Interleave(
new TeardownReceiverGroup(),
new ExclusiveReceiverGroup(
Arbiter.Receive<ComputationCompleteResult>(
true,
portSet,
computationResult => totalSum += computationResult.Result
),
new ConcurrentReceiverGroup(
// Imagine that there is a persistent Receiver registered here
)
)
);
totalSum += computeResult.Result の周りに完全なメモリ バリアを生成する必要がありますか? DispatcherQueue は Dispatcher を使用しないため、ExclusiveReceiverGroup のレシーバー登録のハンドラーはスレッド プールによって呼び出されます。スレッド プールが呼び出すコールバックのメモリ バリアを生成することを読みましたが、それはコールバック参照自体の鮮度を保証するだけですか?
ExclusiveReceiverGroup は他のコードと同時に実行されないため、computerResult.Result による totalSum のインクリメントはアトミックである必要はありません。Interlocked.Add が完全なフェンスを暗黙的に生成することは知っていますが、それを使用せずに逃げることができるかどうかを確認したいだけです。
これは理論上の問題です。上記のコード例のようなコードは実際にはありませんし、そのようなコードのユースケースもありません。したがって、「念のため Interlocked.Add を使用する」という回答は避けたいと思います。これは、「何か新しいことを学びましょう」という質問です。