1

私は 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か? 例外が発生した場合でも、サブスクライバーは を受け取りnullます。

では、Observable から例外をスローする正しい方法は何ですか?

4

2 に答える 2

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); }, () => {});

上記のコードは、Oops! を出力します。二回。

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 が行うことと非常によく似ています。(1 つの違いは、AsyncSubject を使用して操作の結果をキャッシュすることに関係しています。)

于 2012-08-08T19:08:52.080 に答える
0

を使用する場合Observable.Start、最善の方法は単に例外をキャッチしないことです。 観測可能なシーケンスを作成するだけですObservable.Throw。あなたが期待しているように、Observable.Return彼らは を返す内部メソッドから特別なことをしません。これが、コードの一番上の部分から呼び出しを受けてIObservableいない理由です。OnErrorObservable.Throw への呼び出しは、オブザーバブルを作成し、それに対して何もせず、関数から null 値を返します。これは、オブザーバーの に送信されOnNextます。

2 番目のコードには関連する問題があるようです。繰り返しますが、Throw の呼び出しは何もしません。そのサブスクライバーの OnNext アクションも、おそらくあなたが望むものではありません。LoadAllDataFunc一般に、その関数から最初の結果が返されるまでにおそらく返されないため、その関数からnullを返すことになりGetProjectます(Subscribeは通常ブロックしません)。そこでやりたいことは、Select代わりに使用することです。

return LoadAllDataFunc(this.GlobalFileName)
       .Select(data => data.Item1); //should this be Item2?
于 2012-08-08T13:14:50.367 に答える