[英]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.