IObservable глотает исключения по умолчанию? - PullRequest
2 голосов
/ 31 марта 2020

У меня настроен IObservable, и я пытаюсь переключить его с перехода с «холодного» на «горячий». Однако, по чистой глупости, я обнаружил, что где-то в IObservable необработанное исключение - бросок.

Я сразу испугался, потому что Reactive Extensions не дали мне знать об этом необработанном исключении. Я думаю, что поток только что закончился. Теперь я обеспокоен тем, что Rx Extensions будет поглощать другие исключения.

Это код, который я сейчас использую, чтобы активировать IObservable, чтобы он был «горячим». Я ожидал бы, что любые необработанные исключения, которые происходят внутри IObservable, будут всплывать и появляться здесь. Но это не так.

var observable = Observable.Create<>(async a =>
  { 
    ... 
    a.OnNext();
    ...
    a.OnCompleted();
  });

observable = observable.Do(onNext: ..., 
  onCompleted: async () =>
  {
    // This throws the unhandled exception
    await MethodThatThrowsExceptionAsync();
  });


// I would expect any exceptions inside the IObservable to bubble up and be rethrown here.
await observable.LastOrDefaultAsync();  

Я что-то не так делаю? Это ожидаемое поведение? Это кажется чрезвычайно подверженным ошибкам, если это так.

1 Ответ

1 голос
/ 01 апреля 2020

Do для выражения побочных эффектов в уведомлении, а не для фактического изменения самих уведомлений. Бросать ошибки в Do обычно не рекомендуется.

Если мы разберем это, вы захотите запустить задачу после завершения наблюдения, в которой вы можете выбросить исключение, которое всплывает.

Есть оператор, который может шунтировать другое наблюдаемое после его завершения - Concat.

    var observable = Observable.Create<int>(async a =>
    {
        await Task.Delay(1000);
        a.OnNext(0);
        a.OnCompleted();
    });

    observable = observable.Concat(Observable.FromAsync(async () =>
      {
          await Task.Delay(1000); //simulate work

          // This throws the unhandled exception
          throw new Exception("I'm from async");              

          return 1; //type inference
      }));


    // This now throws
    await observable.LastOrDefaultAsync();

PS

Будьте осторожны при использовании async/await вместо Action<>. Они молча терпят неудачу.

Asyn c пустые методы считаются вредными .

...