取消RX.Net Observer正在进行的OnNext方法

时间:2014-11-03 14:43:56

标签: c# events system.reactive reactive-programming cancellation

正如我原来的问题所述(参见Correlate interdependent Event Streams with RX.Net)我有一个RX.net事件流,只要没有触发某个其他事件,它就只能调用观察者的OnNext方法(基本上是'Handle Change- *系统连接时的事件,断开连接时暂停,并在系统重新连接后重新开始处理Change- *事件。

然而,虽然这对新活动顺利进行,但我如何取消/取消取消正在进行的 .OnNext()电话?

2 个答案:

答案 0 :(得分:1)

由于您的观察者已经被编写为接受CancellationToken,我们可以修改您的Rx流以提供一个事件数据。我们将使用我们将在取消订阅流时处理的Rx CancellationDisposable

// 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)));
}

将其与其他问题的解决方案结合起来:

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

当触发TakeUntil子句时,它将取消订阅CancelOnUnsubscribe observable,后者将依次处理CancellationDisposable并导致令牌被取消。当发生这种情况时,您的观察者可以观察此标记并停止其工作。

答案 1 :(得分:0)

SelectMany存在异步重载,但是如果存在类似Do的重载,那么它在语义上更合适。

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);

这很好,因为它也取消了对订阅的取消。

调用

subscription.Dispose()

DataSourceUnloaded.OnNext(x);

会导致CancellationToken被取消。