タスクを実行するためにカスタム スケジューラを使用する必要があり (これらはタスクである必要があります)、スケジューラが同期コンテキストを設定しない (つまり、収集しない、など)ObserveOn
状況があります。以下は、私がそれをやった方法です。さて、これが非同期呼び出しを実行してその結果を待つのに最適な方法であるかどうかは、よくわかりません。これで大丈夫ですか、それともより堅牢または慣用的な方法がありますか?SubscribeOn
SynchronizationContextScheduler
var orleansScheduler = TaskScheduler.Current;
var someObservable = ...;
someObservable.Subscribe(i =>
{
Task.Factory.StartNew(async () =>
{
return await AsynchronousOperation(i);
}, CancellationToken.None, TaskCreationOptions.None, orleansScheduler);
});
待っている必要がない場合はどうなりますか?
<編集:私がここでやっていることの具体的で単純化された例を見つけました。基本的に、私は Orleans で Rx を使用しています。上記のコードは、私がやっていることの必要最小限の図です。私は一般的にこの状況にも興味がありますが。
最終的なコード
Orleans のコンテキストでは、これは少しトリッキーであることがわかりました。を使用する方法がわかりませんObserveOn
。これは、私が使いたいものです。問題は、それを使用すると、Subscribe
が呼び出されないことです。コード:
var orleansScheduler = TaskScheduler.Current;
var factory = new TaskFactory(orleansScheduler);
var rxScheduler = new TaskPoolScheduler(factory);
var someObservable = ...;
someObservable
//.ObserveOn(rxScheduler) This doesn't look like useful since...
.SelectMany(i =>
{
//... we need to set the custom scheduler here explicitly anyway.
//See Async SelectMany at http://log.paulbetts.org/rx-and-await-some-notes/.
//Doing the "shorthand" form of .SelectMany(async... would call Task.Run, which
//in turn runs always on .NET ThreadPool and not on Orleans scheduler and hence
//the following .Subscribe wouldn't be called.
return Task.Factory.StartNew(async () =>
{
//In reality this is an asynchronous grain call. Doing the "shorthand way"
//(and optionally using ObserveOn) would get the grain called, but not the
//following .Subscribe.
return await AsynchronousOperation(i);
}, CancellationToken.None, TaskCreationOptions.None, orleansScheduler).Unwrap().ToObservable();
})
.Subscribe(i =>
{
Trace.WriteLine(i);
});
また、 Codeplex Orleans フォーラムの関連スレッドへのリンク。