Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Rx.Net GroupBy实现缺少元素序列_C#_.net_System.reactive_Reactive Programming_Rx.net - Fatal编程技术网

C# Rx.Net GroupBy实现缺少元素序列

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)

我正在使用RX2.2.5。我有两个视图,用于加载子订单

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

  • 理想情况下,不要在可观察序列中返回空值。它有什么用途?在某些罕见的情况下,这可能有意义,但我经常发现使用null而不是
    OnCompleted
    来表示此序列没有值

  • e、 g

    甚至更好(无嗅探和空检查)


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