忽略Observable中的异常并继续

时间:2015-11-17 00:33:31

标签: c# udp system.reactive

考虑一下这个Observable:

_listener = Observable.Defer(() => _deviceTypeProvider.GetDeviceTypes().ToObservable()
            .SelectMany(CreateUdpListener, CreateMessage)
            .OfType<DeviceMessage>()
            .SelectMany(InjectTestMode)
            .OfType<DeviceMessage>()
            .Do(async message => await PublishMessage(message)))
            .Retry()
            .Subscribe(OnMessageReceive, OnError, OnComplete);

除非CreateMessageInjectTestMode引发异常,否则此方法无效。

我希望Observable跳过生成异常的序列中的项目并继续。

我已经阅读了Catch,但我发现的例子允许你开始一个新的Observable,我想继续我拥有的那个。 此时整个序列重新开始,包括我想尽可能避免的UDP端口。

[更新]

一位同事和我重新阅读了有关使用IEnumerable<IObservable<>>IObservable<IObservable<>>的一些评论,并提出了有效的建议!但这是对的/最佳做法吗?

如果内部可观察到异常,我想知道它是否只会丢弃正在飞行的ReceiveAsync事件中的数据包。

var listeners = Observable.Defer(() => _deviceTypeProvider.GetDeviceTypes()
                .ToObservable()
                .Select(UdpListener)
                .SelectMany(listener =>
                {
                  return Observable.Defer(() => Observable
                    .FromAsync(listener.UdpClient.ReceiveAsync)
                    .Where(x => x.Buffer.Length > 0)
                    .Repeat()
                    .Select(result => CreateMessage(listener.DeviceType, result))
                    .SelectMany(InjectTestMode)
                    .OfType<DeviceMessage>()
                    .Do(async message => await PublishMessage(message)))
                    .Retry();
                })).Retry();

_listener = listeners.Subscribe(OnMessageReceive, OnError, OnComplete);

2 个答案:

答案 0 :(得分:2)

IObservable<T>的文档指定序列必须与此语法匹配:

OnNext* (OnCompleted|OnError)

异常或完成后不能再发出任何值。如果手动创建违反此语法的可观察对象,则在使用任何现有Rx运算符时可能会出现未定义的行为。不好!<​​/ p>

如果您想要获得重试行为,请将您的查询建模为IEnumerable<IObservable<T>>IObservable<IObservable<T>>,其中外IEnumerable<*>IObservable<*>永不抛出。

答案 1 :(得分:0)

创建一些静态扩展函数,将委托传递给它,并将其包装到此函数内的try {} catch {}中。