文件监控系统反应式编程

时间:2018-04-09 12:02:30

标签: c# system.reactive reactivex reactive

我正在使用C#。我是反应式编程的新手。 使用反应式编程,我想创建一个文件夹监控系统,如果文件夹A包含任何文件,如果是,那么它将调用该文件&处理它并在文件夹B中移动它。 假设,文件夹A首先为空。用户将一些文件实时添加到文件夹A中。系统检测到已添加新文件&它将逐个或同时处理它。 我无法理解我应该使用Create或Interval,之后将编写我的处理代码 请帮帮我

2 个答案:

答案 0 :(得分:3)

这应该非常接近:

var query =
    Observable
        .Using(
            () =>
            {
                var fsw = new FileSystemWatcher(@"C:\A");
                fsw.EnableRaisingEvents = true;
                return fsw;
            },
            fsw => Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                h => fsw.Created += h,
                h => fsw.Created -= h))
        .Delay(TimeSpan.FromSeconds(0.1));


query
    .Subscribe(x => File.Move(x.EventArgs.FullPath, Path.Combine(@"C:\B", x.EventArgs.Name)));

答案 1 :(得分:0)

FileSystemWatcher的{​​{3}}相对较小(默认为8 KB,最大64 KB),如果文件系统在短时间内发生突发变化,则很容易超过该值。 FileSystemWatcher的事件处理程序在做任何耗时的事情。 InternalBufferSize给出了以下建议:

将事件处理代码保持尽可能短。

超过缓冲区的后果很严重:所有缓冲的通知都将丢失。在大多数情况下,即使不是完全不能接受的,这也是非常不希望的。因此,应避免在事件调用的同时在同一线程上同步执行繁重的文件移动操作。一种实现所需异步的简单方法是在处理程序和订阅代码之间注入Delay。一种更复杂的方法是将传入的通知排队,并按顺序或使用有限的并发性处理每个文件。 documentation运算符可用于排队和并发控制。这是一个例子¹:

IObservable<Unit> query = Observable
    .Using(() =>
        {
            var fsw = new FileSystemWatcher(@"C:\A");
            fsw.EnableRaisingEvents = true;
            return fsw;
        },
        fsw => Observable.FromEventPattern<FileSystemEventHandler,
            FileSystemEventArgs>(h => fsw.Created += h, h => fsw.Created -= h)
    )
    .Delay(TimeSpan.FromSeconds(0.1))
    .Select(x => Observable.Defer(() => Observable.Start(() =>
    {
        File.Move(x.EventArgs.FullPath, Path.Combine(@"C:\B", x.EventArgs.Name));
    })))
    .Merge(maxConcurrent: 2);

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

Task<Unit> task = query.ToTask(cts.Token); // Start the file-watching

Observable.Defer + Observable.Start组合用作异步Observable.FromAsync的同步等效项(因为File.Move方法是同步的)。

¹它是Enigmativity Merge的修改版本。