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

时间:2014-12-01 08:12:11

标签: c# system.reactive

我正在尝试生成一系列事件,这些事件由文件名组成,这些文件名是目录中的现有文件。

效果很好。代码如下:

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包装在另一个可以按时间触发文件枚举的observable中。 我所有的重复/重播尝试都不会触发文件搜索并生成以前的事件,这不是我想要的。

提前致谢。

编辑1 : 好吧,使用ToObservable()

可以简化代码
Directory.GetFiles(path, filter)
    .ToObservable()
    .Select(s => new FileChangedEvent(s, @"Existing"))

1 个答案:

答案 0 :(得分:-1)

如果您希望在interval上运行文件搜索,可以执行以下操作:

  Observable.Interval(TimeSpan.FromSeconds(2))
    .Select(_ => 
      Directory.GetFiles(path, filter)
     .ToObservable()
     .Select(s => new FileChangedEvent(s, @"Existing"))
   )
   .SelectMany(_ => _)
   .Subscribe(onNewFileChangedEvent => {
     Console.WriteLine(onNewFileChangedEvent.ToString());
   });

但这会产生相同的“现有”文件更改事件,您需要在将它们发送到订阅之前进行重复删除(我猜?)。您可以使用Buffer operator来创建两组文件的差异并仅发出这些文件。

为什么SelectMany()

原始流返回Interval的计时器事件。在每个事件中,我们都会返回FileChangedEvents的新流。

   t1--t2--t3
   \    \   \
    \     \   ---t3{evt1,evt2,evt3}
     \      ---t{evt1,evt2,evt3}
      ---t1{evt1,evt2,evt3}

因为我们希望将这些信息融合到我们的订阅者可以使用的一个流中,所以我们必须合并这些结果。输入SelectMany(),将投影和展平组合成一个步骤。因为我们不是。我们对projection的{​​{1}}属性不感兴趣,我们指出我们将对selectMany强调语法所指示的项目(通过惯例)不执行任何操作。

我不能只使用Merge()运算符吗?

_ => _本质上是标识Merge()的语义等价物(有重载执行控制并发等有趣的事情)。连续生成要合并的序列肯定没有问题。这是original implementation