2

RX 2.2.5 を使用しています。サブオーダーをロードする2つのビューがあります

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

Format Time : (スレッド) : Msg

ご覧のとおり、groupby onNext が 2 回呼び出される前ですが、1 つ逃した後です。ここで 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})

Update2:バグまたは機能の可能性

GroupBy は、fireNewMapEntry が true ( GroupBy.cs ) の場合にのみ groupedObservable を起動し、これがここで発生します。

 if (!_map.TryGetValue(key, out writer))
 {
    writer = new Subject<TElement>();
    _map.Add(key, writer);
    fireNewMapEntry = true;
  }

ここで、_map は typeDictionary<TKey, ISubject<TElement>>です。これが問題になる可能性がありますか?

4

2 に答える 2

1

あなたのコードスタイルに関するいくつかのメモ(申し訳ありませんが、@supertopiが回答したと思うので、実際には回答ではありません)

  1. あなたSubscribeOnObserveOn電話は、最終的なサブスクリプションの前に行う最後のことになります。現在のコードでは、貴重なサイクルを使用して、、、WhereおよびSnoopすべてGroupByを実行しています。_uiScheduler

  2. サブスクライブでのサブスクライブは避けてください。AddIfNewはキーとを受け取るように見えるIObservable<T>ので、内部で何らかのサブスクリプションを実行していると思います。代わりに、あなたが知っていることに頼ってください。GroupBy を使用している場合、グループが最初に生成されたときに Key が一意になることがわかります。したがって、これは単なる Add にすることができます (チェックしているキーの場合)。Take(1)明示的にしたい場合にも使用できます。それがチェックしているキーではない値である場合、それはGroupBy冗長であるように見えます。

  3. 変数名の一貫性を保つようにしてください。別の開発者がクエリを読んでいるときにsubOschildOsとの間をジャンプするのではなく、うまく誘導されるようにします (imo)childUpdateschildOrder

  4. 理想的には、監視可能なシーケンスで null 値を返さないでください。それはどのような目的に役立ちますか?まれに意味がある場合もOnCompletedありますが、このシーケンスに値がないことを示すために、 の代わりに null が使用されることがよくあります。

例えば

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

h番目

于 2016-10-27T09:39:21.767 に答える
0

の性質が欠けていますGroupBy

オペレーターはOnNext、新しいグループが表示された後にのみ出力します (実装GroupBy.cs:67を参照してください)。あなたの場合、orderID両方の通知が等しいため、1つだけOnNextが発行されます。

IGroupedObservable<T>グループ内のさらなる通知にアクセスする必要がある場合は、オペレーターによって発行された値をサブスクライブできます。

于 2016-10-27T06:56:23.683 に答える