C# 可观察到定期处理目录中的文件

C# 可观察到定期处理目录中的文件,c#,system.reactive,C#,System.reactive,我试图生成一系列事件,这些事件由目录中现有文件的文件名组成 这很有效。代码如下所示: Observable.Generate( ExistingFiles(path, filter), Condition(), Iterate(), CreateFileChangedEvent()

我试图生成一系列事件,这些事件由目录中现有文件的文件名组成

这很有效。代码如下所示:

Observable.Generate(
                        ExistingFiles(path, filter),
                        Condition(),
                        Iterate(),
                        CreateFileChangedEvent()
                        )

           private static Func<List<string>.Enumerator, FileChangedEvent> CreateFileChangedEvent()
            {
                return enumerator => new FileChangedEvent(enumerator.Current, @"Existing");
            }

            private static Func<List<string>.Enumerator, List<string>.Enumerator> Iterate()
            {
                return enumerator =>
                {
                    enumerator.MoveNext();
                    return enumerator;
                };
            }

            private static List<string>.Enumerator ExistingFiles(string path, string filter)
            {
                List<string>.Enumerator files =
                    Directory.GetFiles(path, filter)
                    .ToList()
                    .GetEnumerator();
                // Advance the enumerator to the first result
                files.MoveNext();

                return files;
            }

            private static Func<List<string>.Enumerator, bool> Condition()
            {
                return enumerator => enumerator.Current != null;
            }
        }

如果要在计算机上运行文件搜索,可以执行以下操作:

  Observable.Interval(TimeSpan.FromSeconds(2))
    .Select(_ => 
      Directory.GetFiles(path, filter)
     .ToObservable()
     .Select(s => new FileChangedEvent(s, @"Existing"))
   )
   .SelectMany(_ => _)
   .Subscribe(onNewFileChangedEvent => {
     Console.WriteLine(onNewFileChangedEvent.ToString());
   });
但这将产生相同的“现有”文件更改事件,我想在将它们发送到订阅之前,您需要消除重复?。您可以使用创建两组文件的差异,并仅发射这些文件

为什么选择了很多 原始流从间隔返回计时器事件。在每个事件中,我们都返回一个新的FileChangedEvents流

因为我们想把这些数据融合到一个流中,用户可以使用这些数据流,所以我们必须合并这些结果。输入SelectMany,它将投影和展平合并为一个步骤。因为我们对selectMany的projection属性不感兴趣,所以我们表示,我们不会对带有=>u下划线语法的约定所指示的项执行任何操作

我不能只使用合并操作符吗?
Merge本质上是identity SelectMany的语义等价物。有一些重载可以做一些有趣的事情,比如控制并发。连续生成要合并的序列肯定没有问题。以下是

似乎大多数代码都涉及将IEnumerable转换为IObservable。有什么理由不为IEnumerables使用适当的ToObservable扩展方法吗?没有。我将从这个开始。照它的工作原理,并且,正如您所说,为目录中的每个文件发出重复的文件。你能详细介绍一下SelectMany吗?你可以用.Merge代替.SelectMany。\u=>\u我现在用Distinct来过滤已经生成的事件。不再有重复项。@Mark Merge本质上是标识SelectMany的语义等价物。\uMany=>\uMany重载可以执行一些有趣的操作,比如控件并发性。连续生成要合并的序列肯定没有问题。这是最初的实现:@Mark事实上,据我所知,您引用的文档也没有提到任何此类限制-事实上,它明确讨论了使用流作为源…或者甚至是发出可观察的可观察对象。。。
  Observable.Interval(TimeSpan.FromSeconds(2))
    .Select(_ => 
      Directory.GetFiles(path, filter)
     .ToObservable()
     .Select(s => new FileChangedEvent(s, @"Existing"))
   )
   .SelectMany(_ => _)
   .Subscribe(onNewFileChangedEvent => {
     Console.WriteLine(onNewFileChangedEvent.ToString());
   });
   t1--t2--t3
   \    \   \
    \     \   ---t3{evt1,evt2,evt3}
     \      ---t{evt1,evt2,evt3}
      ---t1{evt1,evt2,evt3}