繁体   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