使用 Directory.EnumerateFiles 的可观察异常处理
Observable Exception Handling with Directory.EnumerateFiles
我对以下代码有点困惑:
这是我认为应该发生的事情
directorySearch 作为可观察对象创建,但由于未被枚举而未执行。
Catch 扩展方法应该捕获所有可能的文件系统相关错误,我有一个额外的异常捕获用于调试。
发生了什么:
正在抛出异常! :(
var counter = 0;
var directorySearch = Directory.EnumerateFiles("//.", "*.*", SearchOption.AllDirectories).ToObservable();
directorySearch
.Catch<string, DirectoryNotFoundException>(tx => Observable.Return(string.Empty))
.Catch<string, UnauthorizedAccessException>(tx => Observable.Return(string.Empty))
.Catch<string, PathTooLongException>(tx => Observable.Return(string.Empty))
.Where(next => !string.IsNullOrWhiteSpace(next))
.Select(Path.GetFileName)
.Do(_ => Debug.WriteLine("Logging, update some counter or something.."))
.Do(_ => counter++)
.Subscribe(_ => { Debug.WriteLine("File: " + _); });
counter.Should().Be(18, "because there are that many files in the directory");
似乎是 ToObservable 引起了枚举。
System.IO.DirectoryNotFoundException : Could not find a part of the path 'D:\Projects\DirectorySearching\SearchingSamples\SearchingSamples\bin\Debug\fake'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.CommonInit()
at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
at System.IO.Directory.EnumerateFiles(String path, String searchPattern, SearchOption searchOption)
at SearchingSamples.searching_samples_using_linq.reactive_showing_data_stream_processing() in searching_samples_using_linq.cs: line 47
ToObservable 不会导致枚举发生。
如果传递的路径无效,Directory.EnumerateFiles 将自行抛出所有内容。 MSDN page for Directory.EnumerateFiles 记录了这种行为:
DirectoryNotFoundException: path is invalid, such as referring to an unmapped drive.
如前所述,问题是由于 Directory
class 的标准行为,在这种情况下,异常是在 Observable.ToObservable(TSource)
方法调用之前抛出的。
修复它的 Rx 方法是 "defering" 方法执行,这种技术通常用于将热 observable 转换为冷 observable,这基本上意味着您将创建订阅副作用。
var directorySearch = Observable.Defer(() =>
Directory.EnumerateFiles("//.", "*.*", SearchOption.AllDirectories).ToObservable());
我对以下代码有点困惑:
这是我认为应该发生的事情
directorySearch 作为可观察对象创建,但由于未被枚举而未执行。
Catch 扩展方法应该捕获所有可能的文件系统相关错误,我有一个额外的异常捕获用于调试。
发生了什么:
正在抛出异常! :(
var counter = 0; var directorySearch = Directory.EnumerateFiles("//.", "*.*", SearchOption.AllDirectories).ToObservable(); directorySearch .Catch<string, DirectoryNotFoundException>(tx => Observable.Return(string.Empty)) .Catch<string, UnauthorizedAccessException>(tx => Observable.Return(string.Empty)) .Catch<string, PathTooLongException>(tx => Observable.Return(string.Empty)) .Where(next => !string.IsNullOrWhiteSpace(next)) .Select(Path.GetFileName) .Do(_ => Debug.WriteLine("Logging, update some counter or something..")) .Do(_ => counter++) .Subscribe(_ => { Debug.WriteLine("File: " + _); }); counter.Should().Be(18, "because there are that many files in the directory");
似乎是 ToObservable 引起了枚举。
System.IO.DirectoryNotFoundException : Could not find a part of the path 'D:\Projects\DirectorySearching\SearchingSamples\SearchingSamples\bin\Debug\fake'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.CommonInit()
at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
at System.IO.Directory.EnumerateFiles(String path, String searchPattern, SearchOption searchOption)
at SearchingSamples.searching_samples_using_linq.reactive_showing_data_stream_processing() in searching_samples_using_linq.cs: line 47
ToObservable 不会导致枚举发生。
如果传递的路径无效,Directory.EnumerateFiles 将自行抛出所有内容。 MSDN page for Directory.EnumerateFiles 记录了这种行为:
DirectoryNotFoundException: path is invalid, such as referring to an unmapped drive.
如前所述,问题是由于 Directory
class 的标准行为,在这种情况下,异常是在 Observable.ToObservable(TSource)
方法调用之前抛出的。
修复它的 Rx 方法是 "defering" 方法执行,这种技术通常用于将热 observable 转换为冷 observable,这基本上意味着您将创建订阅副作用。
var directorySearch = Observable.Defer(() =>
Directory.EnumerateFiles("//.", "*.*", SearchOption.AllDirectories).ToObservable());