1つのアイテムしか返さないことがわかっているIObservableにアクセスできる場合、これは機能し、最適な使用パターンですか?
IDisposable disposable = null;
disposable = myObservable.Subscribe(x =>
{
DoThingWithItem(x);
if (disposable != null)
{
disposable.Dispose();
}
});
免責事項:私もまだRxを学んでいます。したがって、私は実際には専門家ではありませんが、Subscribe
によって返される使い捨てはサブスクリプションのサブスクリプションを解除するだけだと思います。また、あなたの場合のようにソースが完了すると、サブスクリプションの解除は自動的に行われます。したがって、Dispose
は冗長であり、安全に削除できると思います。
詳細については、これに対する回答を参照してください 質問 。
Subscribe
拡張メソッドによって返されるディスポーザブルは、監視対象beforeから手動でサブスクライブを解除できるようにするためだけに返されます。
オブザーバブルが-OnCompleted
またはOnError
のいずれかで完了した場合、サブスクリプションは既に破棄されています。
このコードを試してください:
_var xs = Observable.Create<int>(o =>
{
var d = Observable.Return(1).Subscribe(o);
return Disposable.Create(() =>
{
Console.WriteLine("Disposed!");
d.Dispose();
});
});
var subscription = xs.Subscribe(x => Console.WriteLine(x));
_
上記を実行すると、「Disposed!」と表示されます。サブスクリプションで.Dispose()
を呼び出す必要なしに、オブザーバブルが完了すると、コンソールに書き込まれます。
注意すべき重要な点の1つは、ガベージコレクターが監視可能なサブスクリプションで.Dispose()
を呼び出すことはないため、サブスクリプションがない場合はmust破棄します(またはサブスクリプションが範囲外になる前に自然に終了しました。
これを例にとってみましょう:
_var wc = new WebClient();
var ds = Observable
.FromEventPattern<
DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => wc.DownloadStringCompleted += h,
h => wc.DownloadStringCompleted -= h);
var subscription =
ds.Subscribe(d =>
Console.WriteLine(d.EventArgs.Result));
_
ds
observableは、サブスクリプションがある場合にのみイベントハンドラーにアタッチし、オブザーバブルが完了するかサブスクリプションが破棄された場合にのみデタッチします。これはイベントハンドラーであるため、オブザーバブルはさらにイベントを待機しているため完了しません。したがって、イベントから切り離す唯一の方法は破棄です(上記の例の場合)。
FromEventPattern
observableがあり、1つの値しか返さないことがわかっている場合は、サブスクライブする前に.Take(1)
拡張メソッドを追加して、イベントハンドラーを自動的にデタッチできるようにしてから、サブスクリプションを手動で破棄する必要はありません。
そのようです:
_var ds = Observable
.FromEventPattern<
DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => wc.DownloadStringCompleted += h,
h => wc.DownloadStringCompleted -= h)
.Take(1);
_
これがお役に立てば幸いです。
Take
関数は、まさにあなたが探していることを実行します。この場合、Take(1)
。
一部のコメントとは対照的に、OnNext
内からサブスクリプションを破棄することはまったく珍しいことではありません。OnCompleted
とOnError
での廃棄は、Subscribe
拡張メソッドが作成するラップされたサブスクリプションによって行われるのは事実ですが、サブスクライブを解除することもできます。あなたが観察している値(あなたの場合のように:最初のもの)。 1つの値しか生成しないことがわかっているオブザーバブルが常にあるとは限りません。
問題は、サブスクライブした後にのみIDisposable
を取得することです。オブザーバブルは、購読を解除するためにOnNext
を返す前であっても、IDisposable
にコールバックする場合があります(使用するIScheduler
などによって異なります)。
この場合、_System.Reactive.Disposables.SingleAssignmentDisposable
_が便利です。遅れて割り当てる可能性のあるIDisposable
をラップし、それまでにSingleAssignmentDisposable
がすでに破棄されている場合は、割り当て時にすぐに破棄します。また、プロパティIsDisposed
を持ち、最初はfalse
であり、Dispose()
が呼び出されるとtrue
に設定されます。
そう:
_IObservable<string> source = ...;
var subscription = new SingleAssignmentDisposable();
subscription.Disposable = source.Subscribe(x =>
{
if (subscription.IsDisposed) // getting notified though I've told it to stop
return;
DoThingsWithItem(x);
if (x == "the last item I'm interested in")
subscription.Dispose();
});
_