C# Rx.Net GroupBy实现缺少元素序列
我正在使用RX2.2.5。我有两个视图,用于加载子订单C# Rx.Net GroupBy实现缺少元素序列,c#,.net,system.reactive,reactive-programming,rx.net,C#,.net,System.reactive,Reactive Programming,Rx.net,我正在使用RX2.2.5。我有两个视图,用于加载子订单 _transportService .ObserveSubOrder(parentOrder.OrderId) .SubscribeOn(_backgroundScheduler) .ObserveOn(_uiScheduler) .Where(subOs => subOs != null)
_transportService
.ObserveSubOrder(parentOrder.OrderId)
.SubscribeOn(_backgroundScheduler)
.ObserveOn(_uiScheduler)
.Where(subOs => subOs != null)
.Snoop("BeforeGrpBy")
.GroupBy(subOs => subOs.OrderId)
.Subscribe(subOrdUpdates =>
{
AddIfNew(subOrdUpdates.Key, subOrdUpdates.Snoop("AfterGrpBy" + "--" + subOrdUpdates.Key));
})
在groupBy获得所有元素序列之前,groupBy之后的问题是它很少遗漏元素序列。我不认为它存在并发性问题,因为从日志中可以明显看出这一点。自定义Snoop扩展方法用于生成这些日志
16:15:44.8169968 : (1) : BeforeGrpBy: OnNext({ OrderId = 9Zsj8Z4sTRb, OrderType = WNX6, Quantity = 10, Price = 178.78125})
16:15:44.8169968 : (1) : AfterGrpBy--9Zsj8Z4sTRb: Observable obtained
16:15:44.8369988 : (9) : AfterGrpBy--9Zsj8Z4sTRb: Subscribed to on.
16:15:44.8379989 : (1) : BeforeGrpBy: OnNext({ OrderId = 9Zsj8Z4sTRb, OrderType = WNX6, Quantity = 10, Price = 178.78125})
16:15:44.8379989 : (9) : AfterGrpBy--9Zsj8Z4sTRb: Subscription completed.
16:15:44.8590010 : (1) : AfterGrpBy--9Zsj8Z4sTRb: Observable obtained
16:15:44.8600011 : (9) : AfterGrpBy--9Zsj8Z4sTRb: Subscribed to on.
16:15:44.8610012 : (9) : AfterGrpBy--9Zsj8Z4sTRb: Subscription completed.
16:15:44.8620013 : (1) : AfterGrpBy--9Zsj8Z4sTRb: OnNext({ OrderId = 9Zsj8Z4sTRb, OrderType = WNX6, Quantity = 10, Price = 178.78125})
格式化时间:(线程):Msg
正如您所看到的,groupby onNext之前被调用了两次,但之后错过了一次。
这里的Rx语法有什么问题吗?或者它是已知的问题吗?有什么见解会有帮助吗?如果需要进一步澄清,请评论
更新:
添加工作日志/理想日志:
16:15:45.1070258 : (1) : BeforeGrpBy: OnNext({ OrderId = 44Fqp3ubNmL, OrderType = TTT6, Quantity = 39, Price = 130.21875})
16:15:45.1280279 : (1) : AfterGrpBy--44Fqp3ubNmL: Observable obtained
16:15:45.1310282 : (10) : AfterGrpBy--44Fqp3ubNmL: Subscribed to on.
16:15:45.1320283 : (10) : AfterGrpBy--44Fqp3ubNmL: Subscription completed.
16:15:45.1320283 : (1) : AfterGrpBy--44Fqp3ubNmL: OnNext({ OrderId = 44Fqp3ubNmL, OrderType = TTT6, Quantity = 39, Price = 130.21875})
16:15:45.1330284 : (1) : BeforeGrpBy: OnNext({ OrderId = 44Fqp3ubNmL, OrderType = TTT6, Quantity = 39, Price = 130.21875})
16:15:45.1330284 : (1) : AfterGrpBy--44Fqp3ubNmL: Observable obtained
16:15:45.1340285 : (10) : AfterGrpBy--44Fqp3ubNmL: Subscribed to on.
16:15:45.1340285 : (10) : AfterGrpBy--44Fqp3ubNmL: Subscription completed.
16:15:45.1350286 : (1) : AfterGrpBy--44Fqp3ubNmL: OnNext({ OrderId = 44Fqp3ubNmL, OrderType = TTT6, Quantity = 39, Price = 130.21875})
更新2:可能的错误或功能
GroupBy仅在fireNewMapEntry为true时激发groupedObservable,(),这种情况发生在这里
if (!_map.TryGetValue(key, out writer))
{
writer = new Subject<TElement>();
_map.Add(key, writer);
fireNewMapEntry = true;
}
if(!\u map.TryGetValue(键,out writer))
{
writer=新主题();
_map.Add(键、编写器);
fireNewMapEntry=true;
}
其中_map的类型为
字典
。这可能是问题所在吗?您缺少了GroupBy
的本质
只有在新组出现后,操作员才会发出OnNext
(请参见实现)。在您的情况下,两个通知的orderID
相等,因此只发出一个OnNext
操作员发出的值为
IGroupedObservable
,如果您需要访问组内的进一步通知,您可以订阅该值。只是关于您的代码样式的一些注释(抱歉,这不是我认为@supertopi已经回答的答案)
SubscribeOn
和ObserveOn
调用移动到最终订阅之前的最后一件事。在当前代码中,您正在执行Where
、Snoop
和GroupBy
,所有这些都在\u uiScheduler
上执行,占用了宝贵的周期AddIfNew
接受一个键和一个IObservable
,因此我假设它在内部执行一些订阅。相反,依靠你所知道的。如果您使用的是GroupBy,那么您知道在第一次生成组时密钥是唯一的。因此,这现在可以只是一个添加(如果它是您正在检查的密钥)。如果您希望明确,也可以使用Take(1)
。如果是值而不是要检查的键,那么GroupBy
似乎是多余的subOs
、childOs
和childUpdates
之间跳来跳去,因为childOrder
似乎是一个更好的名称(imo)OnCompleted
来表示此序列没有值hth正如我在问题中提到的,这种情况很少发生,几乎是百分之一。。如果你看到groupby之后的日志,会得到2个不同的observable,这将导致2个不同的groupedObservable,因此我希望下一个是2。。我将用工作案例的日志更新问题。我建议您从@LeeCampbell处做笔记,以增强您的querys编码风格。从你的订阅风格来看,可能有一个种族条件隐藏在某个地方,产生了“随机性”。我相信我的回答是正确的,因为
GroupBy
当然会在处理订阅并再次继续订阅后,为同一密钥生成新的IGroupedObsevable
。接受你的第3点。关于第4点。我无法控制可观察序列的生成,因为它来自框架中的不同组件。关于第2点。避免在订阅中使用订阅!(这里有什么缺点)第1点,同意可以删除它,但它是否会导致并发问题,从而导致元素丢失?实际实现没有Snoop,这只是为了调试:),但由于上述原因,确实有空检查。在订阅中订阅意味着您很可能会将订阅扔到地板上(并且摸索着尝试不要太多),这意味着内存泄漏。您也很可能没有额外的错误处理层。而是在查询中合成流。这是一个很好的建议,我通过适当的处理来处理这里的高阶合成。我知道这个解决方案的替代方案,但我担心为什么这种情况不起作用,从逻辑上说,除了GroupBy的内部工作之外,我看不出任何语义上的问题。大多数时候,当我看到人们在Rx中遇到这样的“问题”,他们没有遵循一般的指导,当他们只是“与指导保持一致”。如果没有重新编程,在这里很难提供帮助。但由于groupBy在Rx版本发布的4年中被大量使用,我非常怀疑这是Rx的一个缺陷
_transportService
.ObserveSubOrder(parentOrder.OrderId)
.Where(childOrder => childOrder != null)
.Snoop("BeforeGrpBy")
.GroupBy(childOrder => childOrder.OrderId)
.SelectMany(grp => grp.Take(1).Select(childOrder=>Tuple.Create(grp.key, childOrder))
.SubscribeOn(_backgroundScheduler)
.ObserveOn(_uiScheduler)
.Subscribe(newGroup =>
{
Add(newGroup.Item1, newGroup.Item2);
},
ex=>//obviously we have error handling here ;-)
);
_transportService
.ObserveSubOrder(parentOrder.OrderId)
.Where(childOrder => childOrder != null)
.Snoop("BeforeGrpBy")
.SubscribeOn(_backgroundScheduler)
.ObserveOn(_uiScheduler)
.Subscribe(childOrder =>
{
AddIfNew(childOrder.OrderId, childOrder);
},
ex=>//obviously we have error handling here ;-)
);
var subscription = _transportService
.ObserveSubOrder(parentOrder.OrderId)
.SubscribeOn(_backgroundScheduler)
.ObserveOn(_uiScheduler)
.Subscribe(
childOrder => AddIfNew(childOrder.OrderId, childOrder),
ex=>//obviously we have error handling here ;-)
);