Cancel RX.Net Observer's ongoing OnNext methods

时光总嘲笑我的痴心妄想 提交于 2019-12-24 00:29:13

问题


As described in my original question (see Correlate interdependent Event Streams with RX.Net) I have an RX.net event stream that shall only call the observer's OnNext method as long as a certain other event is not triggered (basically 'Handle Change-* Events as long as the system is connected, pause while disconnected and re-start handling of the Change-* events once the system has re-connected).

However, while this works smoothly with new events, how would I cancel / signal cancellation to ongoing .OnNext() calls?


回答1:


Since your observer is already written to accept a CancellationToken, we can just modify your Rx stream to supply one along with the event data. We'll use the Rx CancellationDisposable that we will dispose of whenever the stream is unsubscribed.

// Converts into a stream that supplies a `CancellationToken` that will be cancelled when the stream is unsubscribed
public static IObservable<Tuple<CancellationToken, T>> CancelOnUnsubscribe<T>(this IObservable<T> source)
{
    return Observable.Using(
        () => new CancellationDisposable(),
        cts => source.Select(item => Tuple.Create(cts.Token, item)));
}

Putting this together with the solution from the other question:

DataSourceLoaded
    .SelectMany(_ => DataSourceFieldChanged
        .Throttle(x)
        .CancelOnUnsubscribe()
        .TakeUntil(DataSourceLoaded))
    .Subscribe(c => handler(c.Item1, c.Item2));

When the TakeUntil clause is triggered, it will unsubscribe from the CancelOnUnsubscribe observable, which will in turn dispose of the CancellationDisposable and cause the token to be cancelled. Your observer can watch this token and stop its work when this happens.




回答2:


There's an async overload of SelectMany, though admittedly if similar overloads of Do existed it would be more semantically appropriate.

var subscription = 
  (from _ in DataSourceLoaded
   from __ in DataSourceFieldChanged
     .Throttle(x)
     .SelectMany(DataSourceFieldChangedAsync)
     .TakeUntil(DataSourceUnloaded)
   select Unit.Default);
  .Subscribe();  // Subscribing for side effects only.

...

async Task<Unit> DataSourceFieldChangedAsync(Field value, CancellationToken cancel);

This is nice because it ties cancellation to the subscription as well.

Calling either

subscription.Dispose()

or

DataSourceUnloaded.OnNext(x);

will cause the CancellationToken to be cancelled.



来源:https://stackoverflow.com/questions/26716527/cancel-rx-net-observers-ongoing-onnext-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!