关于c#:通过FromEventPattern Observer使用Rx超时

Using Rx Timeout with FromEventPattern Observer

我正在尝试在一段时间内没有事件的情况下实施超时。

场景:

我有一个对象,每次接收到消息时都会引发一个事件。
在一段时间(例如20秒)内未收到任何消息(OnReceived事件)时,我想做出反应

这是我到目前为止所拥有的

1
2
3
4
5
6
7
8
9
var observable =  Observable.FromEventPattern<BasicDeliverEventHandler>(
                             handler => _innerConsumer.Received += OnReceived,
                             handler => _innerConsumer.Received -= OnReceived);

var timeout = observable.Timeout(TimeSpan.FromSeconds(20));
using (timeout.Subscribe(_ => { },
              exception =>
              Tracer.Warning("Eventing Consumer timeout : {0}", exception.Message)))
{ }

我正在通过EventPattern创建一个可观察的对象。然后,使用超时。我不明白的是如何从超时中获取异常。我想在发生这种情况时做出反应。

我认为Subcribe方法不是正确的方法,但是那是我从文档中得到的。
如果这不是正确的方法,我愿意提出建议或其他替代方法。

预先感谢


Timeout有问题,因为它终止了序列。 Throttle是您想要的-但是还需要插入一个开始元素,以防万一根本没有任何事件。

我将事件转换为Unit.Default-这在您不关心发生了什么而只是发生了什么的情况下非常有用-并使用StartWith播种油门:

1
2
3
4
5
var timeout = observable.Select(_ => Unit.Default)
                        .StartWith(Unit.Default)
                        .Throttle(TimeSpan.FromSeconds(20);

var subs = timeout.Subscribe(_ => Console.WriteLine("Timeout!"));

出于兴趣,我也有类似的解决方案来检测断开的客户端-这次为多个来源提供了一个超时通知:http://www.zerobugbuild.com/?p=230


让我们看看您拥有的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var observable =
  Observable.FromEventPattern<BasicDeliverEventHandler>(
    handler => _innerConsumer.Received += OnReceived,
    handler => _innerConsumer.Received -= OnReceived
    );

var timeout = observable.Timeout(TimeSpan.FromSeconds(20));

using (timeout.Subscribe(
  _ => { },
  exception =>
  Tracer.Warning("Eventing Consumer timeout : {0}", exception.Message)))
{

}

我们可以这样重写订阅逻辑:

1
2
3
4
5
6
7
var subscription = timeout.Subscribe(
  _ => { }
  exception =>
    Tracer.Warning("Eventing Consumer timeout : {0}", exception.Message)
  );

subscription.Dispose(); // This is bad

由于您的订阅将被立即处理,因此您的观察者没有收到您所期望的通知。

通过删除subscription.Dispose()using语句,观察者在订阅后20秒将收到TimeoutException。但是,由于Exception也会取消订阅,因此您只会收到一次此Exception

此外,Timeout运算符在订阅时开始超时,除非取消订阅或源观察者完成,否则不会取消超时。

您可能想尝试使用其他运算符,例如Throttle

1
2
3
4
observable.Throttle(TimeSpan.FromSeconds(20))
    .Subscribe(x =>
        Console.WriteLine("it has been 20 seconds since we received the last notification.")
        )