c# – 避免在目录中一次更改错误太多

前端之家收集整理的这篇文章主要介绍了c# – 避免在目录中一次更改错误太多前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何避免C#中FileSystemWatcher的错误

too many changes at once in directory

我必须检测网络共享上的所有更改.
InternalBufferSize增加到8192 * 128

解决方法

你应该做两件事:

>将InternalBufferSize设置为支持的最大值(65536).您将其设置为“8192 * 128”的尝试大于documentation中列出的最大支持值,因此您可能根本没有增加缓冲区大小.
>将FileSystemWatcher中的事件排队到后台线程进行处理.

这是第二点,不太了解,真的应该在MSDN上记录.在内部,FileSystemWatcher将更改事件排队到您设置上面大小的内部缓冲区.但重要的是,只有在事件处理程序返回后才会从该缓冲区中删除项目.这意味着事件处理程序引入的每个开销周期都会增加缓冲区填满的可能性.您应该做的是尽快清除FileSystemWatcher的有限队列,并将事件移动到您自己的无限队列中,以您可以处理的速率处理,或者如果您愿意,可以丢弃,但是有一些智能它.

这基本上就是我在代码中所做的.首先,我开始自己的调度程序线程:

Dispatcher changeDispatcher = null;
ManualResetEvent changeDispatcherStarted = new ManualResetEvent(false);
Action changeThreadHandler = () =>
{
    changeDispatcher = Dispatcher.CurrentDispatcher;
    changeDispatcherStarted.Set();
    Dispatcher.Run();
};
new Thread(() => changeThreadHandler()) { IsBackground = true }.Start();
changeDispatcherStarted.WaitOne();

然后我创建了观察者.请注意设置的缓冲区大小.就我而言,我只关注目标目录中的更改,而不是子目录:

FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.InternalBufferSize = 64 * 1024;
watcher.IncludeSubdirectories = false;

现在我附加了我的事件处理程序,但是在这里我将它们调用到我的调度程序而不是在观察程序线程中同步运行它们.是的,调度员将按顺序处理事件:

watcher.Changed += (sender,e) => changeDispatcher.BeginInvoke(new Action(() => OnChanged(sender,e)));
watcher.Created += (sender,e) => changeDispatcher.BeginInvoke(new Action(() => OnCreated(sender,e)));
watcher.Deleted += (sender,e) => changeDispatcher.BeginInvoke(new Action(() => OnDeleted(sender,e)));
watcher.Renamed += (sender,e) => changeDispatcher.BeginInvoke(new Action(() => OnRenamed(sender,e)));

最后,在处理完FileSystemWatcher之后(你正在这样做,对吧?),你需要关闭你的调度员:

watcher.Dispose()
changeDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);

就是这样.在网络和本地场景中,我自己都遇到了这个问题.使用这种方法后,我无法再次生成错误,即使在尽可能快地将空文件敲打到监视目录时也是如此.如果你曾经设法以某种方式耗尽这种情况下的缓冲区(我不确定是否可能,API上游可能更慢),这里还有进一步优化的空间.只要您的调度程序超过了“临界点”,发送方无法以比发送方式更快的速度发布事件,您将永远不会得到积压,因此永远不会破坏缓冲区.我相信这种方法可以让你进入安全区域.

猜你在找的C#相关文章