根据SubscribeOn / ObserverOn

时间:2016-08-05 09:39:14

标签: c# exception-handling task system.reactive

我会尝试解释我的问题并简化。我有一个像这样使用的Observable:

 Disposable = SaveMarketDataSnapshot(dataSet).Subscribe(OnSave, OnErrorSave, OnCompletedSave);

SaveMarketDataSnapshot的定义如下:

IObservable<IMarketDataSet> SaveMarketDataSnapshot(List<IMarketDataSet> dataSet)
{
   var obs =  Save(data);

   obs.ObserveOn(SchedulerService.UiScheduler).Subscribe(TrackSavedDataSet);//(case 1)
   return obs;
}

在SaveMarketDataSnapshot中,我喜欢用于不同目的的跟踪器。

我用Observable.Create创建Observable,运行一个使用REST API调用执行Save操作的任务。

   public IObservable<MarketDataSet> Save(List<KeyValuePair<string, MarketDataSet>> marketDataSet)
    {
        var obs = Observable.Create<MarketDataSet>(observer =>
        {
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            Task task = new Task(() => SaveInternal(marketDataSet, observer, cancellationTokenSource.Token), cancellationTokenSource.Token);

            task.Start();

            return Disposable.Create(() => cancellationTokenSource.Cancel());
        });
        return obs;
    }


    void SaveInternal(List<KeyValuePair<string, MarketDataSet>> dataSets, IObserver<MarketDataSet> observer, CancellationToken cancelToken)
    {
        var exceptions = new List<Exception>();

        try
        {
            foreach (var marketDataSet in dataSets)
            {
                try
                {
                    throw new Exception ();//Simulate Issue 
                    observer.OnNext(marketDataSet.Key);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }
                cancelToken.ThrowIfCancellationRequested();
            }

            if (exceptions.Count > 0)
            {
                AggregateException aggExcep = new AggregateException(
                    "Encountered errors while saving marlket data ",
                    exceptions);
                observer.OnError(aggExcep);
            }
            else
            {
                observer.OnCompleted();
            }
        }
    }

SaveMarketDataSet是一个外部服务

 void SaveMarketDataSet(MarketDataSet, string)

在我的一个测试中,我在运行任务(REST API调用)中遇到异常。幸运的是,我很好地捕获了异常并调用了observer.OnError(ex)

问题在于,当我得到第一个异常时,我的应用程序终止,没有任何异常。经过不同的测试,我了解到TrackSavedDataSet是我崩溃的根源。

我可以通过向我的订阅添加OnError委托来解决问题,但我想了解问题的根源。 我替换旧的订阅(案例2):

 obs.Subscribe(TrackSavedDataSet);

在这种情况下,没有任何事情发生,甚至我的其他订阅的OnErrorSave也没有运行。

最后我用(案例3)替换我的电话:

obs.SubscribeOn(SchedulerService.NewTaskScheduler).
       Subscribe(TrackSavedDataSet);

在这种情况下,调用OnErrorSave并获得UnobservedTaskException。

我认为这个问题的根源是没有处理第二个观察者的OnError并且重新抛出异常。

我有这个假设来解释这3个行为:

案例1:在UI线程中抛出异常并停止应用程序?

案例2:异常抛出用于运行observable的同一个任务,这甚至打破了第一个订阅OnError通知?

案例3:在运行observable(SchedulerService.NewTaskScheduler)的Task中抛出异常而没有catch被认为是未观察到的?

可以请某人澄清这些行为吗?

0 个答案:

没有答案