[英]Reactive Extensions error handling with Observable SelectMany
我正在尝试使用反应式扩展库在某个文件夹上编写文件观察程序这个想法是监视硬盘文件夹中的新文件,等到文件完全写入并将事件推送给订阅者。 我不想使用FileSystemWatcher
因为它为同一个文件引发了两次 Changed 事件。
所以我用“反应式”(我希望)写了它,如下所示:
var provider = new MessageProviderFake();
var source = Observable.Interval(TimeSpan.FromSeconds(2), NewThreadScheduler.Default).SelectMany(_ => provider.GetFiles());
using (source.Subscribe(_ => Console.WriteLine(_.Name), () => Console.WriteLine("completed to Console")))
{
Console.WriteLine("press Enter to stop");
Console.ReadLine();
}
但是我找不到处理错误的“反应方式”。 例如,文件目录可能位于外部驱动器上,但由于连接问题而变得不可用。 所以我添加了GetFilesSafe
来处理来自 Reactive Extensions 的异常错误:
static IEnumerable<MessageArg> GetFilesSafe(IMessageProvider provider)
{
try
{
return provider.GetFiles();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return new MessageArg[0];
}
}
并像使用它一样
var source = Observable.Interval(TimeSpan.FromSeconds(2), NewThreadScheduler.Default).SelectMany(_ => GetFilesSafe(provider));
即使引发异常,是否有更好的方法让SelectMany
调用provider.GetFiles()
? 在这种情况下,我使用错误计数器重复读取操作 N 次,然后失败(终止进程)。
Reactive Extensions 中是否有“尝试 N 次并在尝试之间等待 Q 秒”?
GetFilesSafe
也有一个问题:它返回IEnumerable<MessageArg>
用于延迟读取,但是它可以在迭代时引发并且异常将在SelectMany
某处抛出
有一个Retry
扩展,如果当前一个错误,它只会再次订阅 observable,但听起来这不会提供你想要的灵活性。
您可以使用Catch
构建一些东西,如果外部发生错误,它会订阅您提供的 observable。 类似于以下内容(未经测试):
IObservable<Thing> GetFilesObs(int times, bool delay) {
return Observable
.Return(0)
.Delay(TimeSpan.FromSeconds(delay ? <delay_time> : 0))
.SelectMany(_ => Observable.Defer(() => GetFilesErroringObservable()))
.Catch(Observable.Defer(() => GetFilesObs(times - 1, true)));
}
// call with:
GetFilesObs(<number_of_tries>, false);
正如所写的,除了触发重试之外,这对错误没有任何作用。 特别是,当发生了足够多的错误时,它会在没有错误的情况下完成,这可能不是您想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.