Observable.Throw的例子

时间:2012-08-08 07:14:27

标签: c# system.reactive

我对Observables有点新意,所以我只是想找一个能让我朝着正确方向前进的例子(教程可能吗?)。所以这就是 - 我想创建异步Observable并从中提出Exception。这是我的例子:

    protected IObservable<Tuple<DataPart1, DataPart2>> LoadAllDataFunc(string FileName)
    {
        return Observable.Start<Tuple<DataPart1, DataPart2>>(() =>
        {
            ConfigReaderWriter readerWriter = new ConfigReaderWriter();
            try
            {
                readerWriter.UnpackFile(fileName, out DataPart1, out DataPart2);
                return Tuple.Create(DataPart1, DataPart2);
            }
            catch (Exception exp_gen)
            {
                Observable.Throw<Exception>(exp_gen);
                return null;
            }
        });
    }

问题是我不认为我没有正确地抛出Exception。例如 - 任何订阅者:

    internal IObservable<DataPart2> GetProject()
    {
        if (this.GlobalDataPart2 != null)
            return Observable.Return(GlobalDataPart2);

        IObservable<Project> receivedData = null;

        var loadAll = LoadAllDataFunc(this.GlobalFileName).Subscribe(
                data => { receivedData = Observable.Return(data.Item1); },
                (ex) => { Observable.Throw<Exception>(ex); }
            );

        return receivedData;
    }

不会从Exception收到LoadAllDataFunc?即使发生 if 异常,订阅者也会收到null

那么 - 从Observable抛出异常的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

只是为了清楚地说明Observable.Throw的作用:它返回一个可观察的序列(指定的元素类型),其唯一的作用是通过调用它们的OnError方法告诉所有观察者一个异常:

var err = Observable.Throw<int>(new Exception("Oops!"));
err.Subscribe(_ => {}, ex => { Console.WriteLine(ex.Message); }, () => {});
err.Subscribe(_ => {}, ex => { Console.WriteLine(ex.Message); }, () => {});

上面的代码将打印出来!两次。

正如Gideon所提到的,像Start这样的运算符会将用户异常传播到OnError通道。如果您使用Observable.Create,请直接与观察者讨论错误情况:

var res = Observable.Create<int>(observer =>
{
    return scheduler.Schedule(() =>
    {
        var res = default(int);

        try
        {
            res = ComputationThatMayFail();
        }
        catch (Exception ex)
        {
            observer.OnError(ex);
            return;
        }

        observer.OnNext(res);
        observer.OnCompleted();
    });
});

事实上,上面显示的代码非常接近Start所做的事情。 (一个区别与使用AsyncSubject缓存操作的结果有关。)

答案 1 :(得分:0)

使用Observable.Start时,最好的方法是不捕获异常。 Observable.ThrowObservable.Return只是创建可观察的序列;他们没有像返回IObservable那样在内部方法做任何特别的事情,就像你期望的那样。这就是为什么你没有从你的顶级代码中获得OnError电话。对Observable.Throw的调用创建了一个observable,对它没有任何作用,并从函数返回一个空值,然后发送给观察者的OnNext

您的第二段代码似乎有相关问题。再次,对Throw的召唤将无所作为。该订户的OnNext操作也可能不是您想要的。通常,您将从该函数返回null,因为LoadAllDataFunc的第一个结果可能不会在GetProject返回时出现(订阅通常不会阻止。)我猜你想要什么是否可以使用Select

return LoadAllDataFunc(this.GlobalFileName)
       .Select(data => data.Item1); //should this be Item2?