簡體   English   中英

卡在Rx Observable SelectMany中

[英]Stuck with Rx Observable SelectMany

我的目標是通過ftp下載文件並以某種方式異步處理它們。 我將文件列表轉換為IObservable,並使用SelectMany組合器對其進行處理。 里面有一些操作來下載被阻止的文件:嘗試下載具有重試次數的文件並返回Tuple,或者在失敗的情況下返回Tuple並將其包裝到Observable中。 我已將“延遲后可觀察到的可重試”的樣本帶到那里,並對其進行了一些修改。 問題是我的代碼在下載了幾個文件后隨機停止。 有時,它到達“訂閱”方法中的“ OnNext”回調。 我從未檢測到到達“ OnComplete”回調的代碼。 也不例外。

        files.ToObservable().SelectMany(f =>
        {
            var source = Observable.Defer(() => Observable.Start(() =>
            {
                ftpConnection.DownloadFile(avroPath, f.Name);
                return Tuple.Create(true, f.Name);
            }));
            int attempt = 0;
            return Observable.Defer(() => ((++attempt == 1)
                ? source
                : source.DelaySubscription(TimeSpan.FromSeconds(1))))
                .Retry(4)
                .Catch(Observable.Return(Tuple.Create(false, f.Name)));
        }).Subscribe(
            res =>
            {
                Console.Write("Damn, its only rarely gets there, however some files were downloaded succesfully");
                if (res.Item1) Process(res.Item2);
                else LogOrQueueOrWhatever(res.Item2);
            },
            (Exception ex) =>
            {
                Console.Write("Never was thrown");
            },
            () =>
            {
                Console.Write("Never entered this section");
                ProcessLogs();
                ScheduleNExtDownloadRoutine();
            });

如果有人會表現出更慣用的方式與Observables上的組合器打交道,我將不勝感激。

正如布蘭登(Brandon)所述,在定義可觀察行為之后,沒有同步/阻塞。 因此,我通過將“ Subscribe”調用替換為“ ForEachAsync”,將該Observable轉換為Task並使用Tasks的“ Wait”方法阻止調用者來處理它:

    files.ToObservable().SelectMany(f =>
    {
        var source = Observable.Defer(() => Observable.Start(() =>
        {
            ftpConnection.DownloadFile(avroPath, f.Name);
            return Tuple.Create(true, f.Name);
        }));
        int attempt = 0;
        return Observable.Defer(() => ((++attempt == 1)
            ? source
            : source.DelaySubscription(TimeSpan.FromSeconds(1))))
            .Retry(4)
            .Catch(Observable.Return(Tuple.Create(false, f.Name)));
    }).ForEachAsync(res =>
    {
        if (res.Item1) Process(res.Item2);
        else LogOrQueueOrWhatever(res.Item2);
    }).Wait();

    ProcessLogs();
    ScheduleNExtDownloadRoutine();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM