gpt4 book ai didi

c# - FileSystemWatcher 跳过一些事件

转载 作者:太空狗 更新时间:2023-10-30 00:39:50 26 4
gpt4 key购买 nike

如果你用谷歌搜索 FileSystemWatcher 问题,你会发现很多关于 FileSystemWatcher 跳过一些事件(不触发所有事件)的文章。基本上,如果您更改监视文件夹中的大量文件,其中一些将不会被 FileSystemWatcher 处理。

为什么会这样,我怎样才能避免错过事件?

最佳答案

原因

FileSystemWatcher 正在监视某个文件夹中发生的更改。当文件发生变化时(例如创建文件),FileSystemWatcher 会引发相应的事件。事件处理程序可能会解压缩文件,读取其内容以决定如何进一步处理它,将其记录写入数据库日志表并将文件移动到另一个文件夹。处理文件可能需要一些时间。

在此期间,可能会在监视文件夹中创建另一个文件。由于 FileSystemWatcher 的事件处理程序正在处理第一个文件,它无法处理第二个文件的创建事件。因此,FileSystemWatcher 错过了第二个文件。 enter image description here

解决方案

由于文件处理可能需要一些时间,并且 FileSystemWatcher 可能无法检测到其他文件的创建,因此文件处理应与文件更改检测分开,并且文件更改检测应尽可能短,以免错过任何一个文件更改。文件处理可以分为两个线程:一个用于文件更改检测,另一个用于文件处理。当文件被更改并且它被 FileSystemWatcher 检测到时,适当的事件处理程序应该只读取它的路径,将它转发给文件处理线程并关闭自身,以便 FileSystemWatcher 可以检测到另一个文件更改并使用相同的事件处理程序。处理线程可能会花费处理文件所需的时间。队列用于将文件路径从事件处理程序线程转发到处理线程。 enter image description here

这是典型的生产者-消费者问题。有关生产者-消费者队列的更多信息,请参见here .

代码

using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;

namespace FileSystemWatcherExample {
class Program {
static void Main(string[] args) {
// If a directory and filter are not specified, exit program
if (args.Length !=2) {
// Display the proper way to call the program
Console.WriteLine("Usage: Watcher.exe \"directory\" \"filter\"");
return;
}

FileProcessor fileProcessor = new FileProcessor();

// Create a new FileSystemWatcher
FileSystemWatcher fileSystemWatcher1 = new FileSystemWatcher();

// Set FileSystemWatcher's properties
fileSystemWatcher1.Path = args[0];
fileSystemWatcher1.Filter = args[1];
fileSystemWatcher1.IncludeSubdirectories = false;

// Add event handlers
fileSystemWatcher1.Created += new System.IO.FileSystemEventHandler(this.fileSystemWatcher1_Created);

// Start to watch
fileSystemWatcher1.EnableRaisingEvents = true;

// Wait for the user to quit the program
Console.WriteLine("Press \'q\' to quit the program.");
while(Console.Read()!='q');

// Turn off FileSystemWatcher
if (fileSystemWatcher1 != null) {
fileSystemWatcher1.EnableRaisingEvents = false;
fileSystemWatcher1.Dispose();
fileSystemWatcher1 = null;
}

// Dispose fileProcessor
if (fileProcessor != null)
fileProcessor.Dispose();
}

// Define the event handler
private void fileSystemWatcher1_Created(object sender, FileSystemEventArgs e) {
// If file is created...
if (e.ChangeType == WatcherChangeTypes.Created) {
// ...enqueue it's file name so it can be processed...
fileProcessor.EnqueueFileName(e.FullPath);
}
// ...and immediately finish event handler
}
}


// File processor class
class FileProcessor : IDisposable {
// Create an AutoResetEvent EventWaitHandle
private EventWaitHandle eventWaitHandle = new AutoResetEvent(false);
private Thread worker;
private readonly object locker = new object();
private Queue<string> fileNamesQueue = new Queue<string>();

public FileProcessor() {
// Create worker thread
worker = new Thread(Work);
// Start worker thread
worker.Start();
}

public void EnqueueFileName(string FileName) {
// Enqueue the file name
// This statement is secured by lock to prevent other thread to mess with queue while enqueuing file name
lock (locker) fileNamesQueue.Enqueue(FileName);
// Signal worker that file name is enqueued and that it can be processed
eventWaitHandle.Set();
}

private void Work() {
while (true) {
string fileName = null;

// Dequeue the file name
lock (locker)
if (fileNamesQueue.Count > 0) {
fileName = fileNamesQueue.Dequeue();
// If file name is null then stop worker thread
if (fileName == null) return;
}

if (fileName != null) {
// Process file
ProcessFile(fileName);
} else {
// No more file names - wait for a signal
eventWaitHandle.WaitOne();
}
}
}

private ProcessFile(string FileName) {
// Maybe it has to wait for file to stop being used by process that created it before it can continue
// Unzip file
// Read its content
// Log file data to database
// Move file to archive folder
}


#region IDisposable Members

public void Dispose() {
// Signal the FileProcessor to exit
EnqueueFileName(null);
// Wait for the FileProcessor's thread to finish
worker.Join();
// Release any OS resources
eventWaitHandle.Close();
}

#endregion
}
}

关于c# - FileSystemWatcher 跳过一些事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33048619/

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