1

Switch ステートメントを使用した Rx サブスクリプションに問題があります。

_performSearchSubject
            .AsObservable()
            .Select(_ => PerformQuery())
            .Switch()
            .ObserveOn(_synchronizationContextService.SynchronizationContext)
            .Subscribe(DataArrivedForPositions, PositionQueryError, PositionQueryCompleted)
            .DisposeWith(this);

フローは次のとおりです。

  1. 一部のプロパティが変更され、 performSearchSubject.OnNext が呼び出されます
  2. ヒットするたびにオブザーバーを返す PerformPositionQuery() が呼び出されます。
  3. このオブザーバーを介して応答するサービスは、データ受信が完了すると OnNext を 2 回呼び出し、OnCompleted を 1 回呼び出します。
  4. メソッド DataArrivedForPositions が予想どおり 2 回呼び出される
  5. データ サービス内でobserver.OnCompleted()が呼び出されますが、メソッドPositionQueryCompletedは呼び出されません。

dataService のコードは次のとおりです。

        protected override void Request(Request request, IObserver<Response> observer)
        {
            query.Arrive += p => QueryReceive(request.RequestId, p, observer, query);
            query.Error += (type, s, message) => QueryError(observer, message);
            query.NoMoreData += id => QueryCompleted(observer);

            query.Execute(request);
        }

        private void QueryError(IObserver<PositionSheetResponse> observer, string message)
        {
            observer.OnError(new Exception(message));
        }

        private void QueryCompleted(IObserver<PositionSheetResponse> observer)
        {
            observer.OnCompleted();
        }

        private void QueryReceive(Guid requestId, Qry0079Receive receiveData, IObserver<PositionSheetResponse> observer, IQry0079PositionSheet query)
        {
            observer.OnNext(ConvertToResponse(requestId, receiveData));
        }
4

1 に答える 1

3

Switch_performSearchSubject結果は、外側のオブザーバブル ( ) が完了したときにのみ完了します。あなたの場合、これは決して行わないと思います(おそらく、検索を実行するユーザーアクションにバインドされています)。

不明なのは、いつPositionQueryCompleted呼び出されると予想されるかです。成功したすべてのクエリが処理された後であれば、ストリームを変更する必要があります。これSwitchは、クエリ ストリームが完了したという情報が失われるためです。ただし、データが実際にあったかどうかを示す UI に関する情報 (スケジューラが間違っていても) も不足しています。処理されます。

それを達成する方法は他にもあるかもしれませんが、基本的には、クエリ ストリームを完全に存続させたいと考えていますSwitch(現在、このイベントは無視されます)。たとえば、クエリ ストリームを変換して、n+1 個のイベントを持ち、完全なイベントを 1 つ追加できます。

    _performSearchSubject
        .AsObservable()
        .Select(_ => 
                  PerformQuery()
                  .Select(Data => new { Data, Complete = false})
                  .Concat(Observable.Return(new { Data = (string)null, Complete = true })))

安全に申し込むことができます.Switch().ObserveOn(_synchronizationContextService.SynchronizationContext)が、サブスクリプションを変更する必要があります。

    .Subscribe(data => {
        if (data.Complete) DataArrivedForPositions(data.Data);
        else PositionQueryCompleted()
    }, PositionQueryError)
于 2015-12-28T15:40:39.617 に答える