Directory.EnumerateFiles 的可观察异常处理



我对以下代码有点困惑:

这是我认为应该发生的事情

  1. 目录搜索是作为可观察量创建的,但由于未枚举,因此不会执行。

  2. Catch 扩展方法应该捕获所有可能的文件系统相关错误,我有一个额外的异常捕获用于调试。

发生了什么事情:

  1. 正在抛出异常! :(

    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:ProjectsDirectorySearchingSearchingSamplesSearchingSamplesbinDebugfake'.
    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 将自行抛出所有内容。Directory.EnumerateFiles 的 MSDN 页记录了以下行为:

DirectoryNotFoundException:路径无效,例如引用未映射的驱动器。

如前所述,问题是由于Directory类的标准行为,在这种情况下,异常是在方法调用之前引发Observable.ToObservable(TSource)

修复它的 Rx 方法是"延迟"方法执行,这种技术通常用于将热可观察量转换为冷可观察量,这基本上意味着您将创建订阅副作用。

var directorySearch = Observable.Defer(() => 
                                 Directory.EnumerateFiles("//.", "*.*", SearchOption.AllDirectories).ToObservable());

最新更新