使用Directory.EnumerateFiles进行可观察的异常处理

时间:2015-01-30 04:02:37

标签: c# system.reactive reactive-programming

我对以下代码感到困惑:

以下是我认为应该发生的事情

  1. directorySearch被创建为一个observable但由于未被枚举而未被执行。

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

  3. 发生了什么:

    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");
      
    2. 似乎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
      

2 个答案:

答案 0 :(得分:4)

ToObservable不会导致枚举发生。

如果传递的路径无效,Directory.EnumerateFiles将自行抛出所有内容。 MSDN page for Directory.EnumerateFiles记录了这种行为:

  

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

答案 1 :(得分:3)

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

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

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