考虑一下这个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);
除非CreateMessage
或InjectTestMode
引发异常,否则此方法无效。
我希望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);
答案 0 :(得分:2)
IObservable<T>
的文档指定序列必须与此语法匹配:
OnNext* (OnCompleted|OnError)
异常或完成后不能再发出任何值。如果手动创建违反此语法的可观察对象,则在使用任何现有Rx运算符时可能会出现未定义的行为。不好!</ p>
如果您想要获得重试行为,请将您的查询建模为IEnumerable<IObservable<T>>
或IObservable<IObservable<T>>
,其中外IEnumerable<*>
或IObservable<*>
永不抛出。
答案 1 :(得分:0)
创建一些静态扩展函数,将委托传递给它,并将其包装到此函数内的try {} catch {}中。