问题描述
我正在使用.Net Framework开发Windows程序。
我想创建一个使用FileSystemWatcher在特定文件夹中创建文件时执行功能的程序。
下面是我的代码。
public async Task<int> CollectFunc() {
string path = @"C:\test";
try
{
FileSystemWatcher watcher = new FileSystemWatcher
{
Path=path
Filter="test.log"
};
watcher.Created += new FileSystemEventHandler(WatcherFunc);
watcher.IncludeSubdrectories=true;
watcher.EnableRaisingEvents=true;
}
catch
{
Console.WriteLine("Error");
}
while(true)
{
await Task.Delay(100000);
}
}
public async void WatcherFunc(object source,FileSystemEventArgs e) {
Console.WriteLine("File Created: " + e.FullPath);
}
9月1日,创建以下文件。 C:\ test \ 20200901 \ test.log 然后,程序将打印“创建的文件:C:\ test \ 20200901 \ test.log”。
9月2日 C:\ test \ 20200902 \ test.log文件已创建, 然后程序将输出“文件已创建:C:\ test \ 20200902 \ test.log”。
...
但是有时Watcher无法正常工作,我必须重新启动程序。
请让我知道是否有比我的源代码更好或更稳定的逻辑。
期待您的答复。
解决方法
尝试以下更改:
// Introduce a class field,to prevent the watcher reference from going out of scope.
private FileSystemWatcher watcher = null;
public void CollectFunc() { // no need for async any more ...
string path = @"C:\test";
try
{
// Init class field
watcher = new FileSystemWatcher
{
Path=path
Filter="test.log"
};
watcher.Created += new FileSystemEventHandler(WatcherFunc);
watcher.IncludeSubdrectories=true;
watcher.EnableRaisingEvents=true;
}
catch (Exception ex)
{
// Better know what the problem actually was.
Console.WriteLine($"Error: {ex.Message}");
}
// It's a winforms app - we don't need to block this => away with while(true)
}
public async void WatcherFunc(object source,FileSystemEventArgs e)
{
// Just in case,catch and log exceptions
try{
Console.WriteLine("File Created: " + e.FullPath);
} catch( Exception ex ) {
// TODO: Log Exception or handle it.
}
}
最重要的是:这是一个已知的问题,更改的次数和频率可能会导致某些缓冲区在观察器中溢出(如果仍然适用,但我记得几年前就遇到过)。 / p>
此处提到了缓冲区溢出问题:https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.internalbuffersize?view=netcore-3.1#remarks
也许值得向Error
事件注册处理程序:https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.error?view=netcore-3.1
我想您在事件处理程序中的Console.WriteLine
只是示例代码,实际上您要做的还不止这些。过去,我发现如果我在这里保持代码很小并尽快处理事件,它将减轻FileSystemWatcher缓冲区的压力。
所以,我所做的就是将文件路径排队入队列,并在另一个线程上处理该队列。这样可以确保事件尽快得到处理,而不会丢失任何事件。窥视会被队列变大而捕获,并由另一个线程独立处理。换句话说:事物堆积在观察者的缓冲区之外。