我的目标是通过ftp下载文件,并以某种方式异步处理它们。 我将文件列表转换为IObservable并使用SelectMany组合器处理它。在里面有一些操作来下载被阻止的文件:尝试下载具有重试次数的文件并返回Tuple,或者在失败的情况下返回Tuple并将其包装到Observable中。 "可观察的样本在延迟后可恢复"我已经对there进行了略微修改。 问题是我的代码在下载几个文件后随机停止。有时它会到达" 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上显示出更加惯用的混淆器方法,我将不胜感激。
答案 0 :(得分:1)
正如Brandon所说,在定义可观察行为之后没有同步/阻塞。所以我通过替换"订阅"来处理它。使用" 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();