gpt4 book ai didi

c# - 如何改进这个 Rx FolderWatcher?

转载 作者:太空宇宙 更新时间:2023-11-03 21:23:25 25 4
gpt4 key购买 nike

<分区>

我从此处提供的示例开始我的示例:http://www.jaylee.org/post/2012/08/26/An-update-to-matthieumezil-Rx-and-the-FileSystemWatcher.aspx但问题是,如果您正在查看一个文件夹,其中有许多文件一直被修改/创建/删除,它永远不会返回事件,因为 throttle 永远不会停止。

我需要的是为每个被更改的文件创建一个新的临时流,并且只发送最后一个事件(如果是删除事件,我们不会通知)。

我认为我的示例可以正常工作,但由于这是我第一次使用 Rx,所以我想就如何简化它获得一些反馈。

这里是:

public class FileWatcher
{
public class FileChangedEvent
{
public string FullPath { get; private set; }
public bool IsFileDeleted { get; private set; }

public FileChangedEvent(string path, bool isFileDeleted = false)
{
FullPath = path;
IsFileDeleted = isFileDeleted;
}
}

public static IObservable<FileChangedEvent> ObserveFolderChanges(string path, string filter, TimeSpan throttle)
{
return Observable.Create<FileChangedEvent>(
observer =>
{
var fileSystemWatcher = new FileSystemWatcher(path, filter) { EnableRaisingEvents = true };

var sources = CreateSources(fileSystemWatcher);

var fileSources = new ConcurrentDictionary<string, Subject<FileChangedEvent>>();
return sources.Merge().Subscribe(fileChange =>
{
Subject<FileChangedEvent> fileSubject = fileSources.GetOrAdd(fileChange.FullPath, (key) =>
{
//Create a new stream for this file.
var addedFileSubject = new Subject<FileChangedEvent>();
addedFileSubject.Throttle(throttle).Subscribe(lastFileChange =>
{
if (lastFileChange != null)
{
Subject<FileChangedEvent> dummy;
fileSources.TryRemove(lastFileChange.FullPath, out dummy);

//Only send the event if the file was not deleted.
if (!lastFileChange.IsFileDeleted)
{
observer.OnNext(lastFileChange);
}
}
});
return addedFileSubject;
});

fileSubject.OnNext(fileChange);
});
}
);
}

private static IObservable<FileChangedEvent>[] CreateSources(FileSystemWatcher fileWatcher)
{
return new[]
{
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs >(handler => fileWatcher.Created += handler, handler => fileWatcher.Created -= handler)
.Select(ev => new FileChangedEvent(ev.EventArgs.FullPath)),

Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs >(handler => fileWatcher.Deleted += handler, handler => fileWatcher.Deleted -= handler)
.Select(ev => new FileChangedEvent(ev.EventArgs.FullPath, true)),

Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs >(handler => fileWatcher.Changed += handler, handler => fileWatcher.Changed -= handler)
.Select(ev => new FileChangedEvent(ev.EventArgs.FullPath)),

//The rename source needs to send a delete event for the old file name.
Observable.Create<FileChangedEvent>(nameChangedObserver =>
{
return Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>(handler => fileWatcher.Renamed += handler, handler => fileWatcher.Renamed -= handler)
.Subscribe(ev =>
{
nameChangedObserver.OnNext(new FileChangedEvent(ev.EventArgs.FullPath));
nameChangedObserver.OnNext(new FileChangedEvent(ev.EventArgs.OldFullPath, true));
});
}),

Observable.FromEventPattern<ErrorEventHandler, ErrorEventArgs >(handler => fileWatcher.Error += handler, handler => fileWatcher.Error -= handler)
.SelectMany(ev => Observable.Throw<FileChangedEvent>(ev.EventArgs.GetException()))
};
}

static void Main(string[] args)
{
var fileWatcher =
FileWatcher.ObserveFolderChanges("Test Path Here", "*.*", TimeSpan.FromSeconds(30))
.Subscribe(fce => { if(fce != null) Console.WriteLine("Changed :" + fce.FullPath); }, e => Debug.WriteLine(e));

Console.ReadLine();
}
}

此用例是在文件路径上的文件上传完成时收到通知。

所以,我的问题是:
1)是否可以简化这个?
2) 我是不是漏了什么?
3) 与没有 Rx 的情况下这样做相比,性能有很大的损失吗?

谢谢!

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com