【发布时间】:2011-08-04 15:11:33
【问题描述】:
我想使用 FileSystemWatcher 来监视目录及其子目录中移动的文件。然后我想在所有文件都被移动后触发一些代码。但我不知道怎么做。我的代码会在每次移动文件时触发,如果用户一次移动多个文件,我只希望它为所有文件触发一次。所以基本上我想创建一个列表,一旦完成所有文件的移动,我想对该列表做一些事情......
代码如下:
class Monitor
{
private List<string> _filePaths;
public void CreateWatcher(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += new
FileSystemEventHandler(watcher_FileCreated);
watcher.Path = path;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
_filePaths.Add(e.FullPath);
Console.WriteLine("Files have been created or moved!");
}
}
更新:尝试使用 Chris 的代码,但它不起作用(请参阅我在 Chris 的回答中的评论):
class Monitor
{
private List<string> _filePaths;
private Timer _notificationTimer;
private FileSystemWatcher _fsw;
public Monitor(string path)
{
_notificationTimer = new Timer();
_notificationTimer.Elapsed += notificationTimer_Elapsed;
// CooldownSeconds is the number of seconds the Timer is 'extended' each time a file is added.
// I found it convenient to put this value in an app config file.
int CooldownSeconds = 1;
_notificationTimer.Interval = CooldownSeconds * 1000;
_fsw = new FileSystemWatcher();
_fsw.Path = path;
_fsw.IncludeSubdirectories = true;
_fsw.EnableRaisingEvents = true;
// Set up the particulars of your FileSystemWatcher.
_fsw.Created += fsw_Created;
}
private void notificationTimer_Elapsed(object sender, ElapsedEventArgs e)
{
//
// Do what you want to do with your List of files.
//
Console.Write("Done");
// Stop the timer and wait for the next batch of files.
_notificationTimer.Stop();
// Clear your file List.
_filePaths = new List<string>();
}
// Fires when a file is created.
private void fsw_Created(object sender, FileSystemEventArgs e)
{
// Add to our List of files.
_filePaths.Add(e.Name);
// 'Reset' timer.
_notificationTimer.Stop();
_notificationTimer.Start();
}
}
更新 2:
根据安德斯的回答试过这个:
public class FileListEventArgs : EventArgs
{
public List<string> FileList { get; set; }
}
public class Monitor
{
private List<string> filePaths;
private ReaderWriterLockSlim rwlock;
private Timer processTimer;
public event EventHandler FileListCreated;
public void OnFileListCreated(FileListEventArgs e)
{
if (FileListCreated != null)
FileListCreated(this, e);
}
public Monitor(string path)
{
filePaths = new List<string>();
rwlock = new ReaderWriterLockSlim();
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += watcher_FileCreated;
watcher.Path = path;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
private void ProcessQueue()
{
List<string> list = new List<string>();
try
{
Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
rwlock.EnterReadLock();
}
finally
{
if (processTimer != null)
{
processTimer.Stop();
processTimer.Dispose();
processTimer = null;
OnFileListCreated(new FileListEventArgs { FileList = filePaths });
filePaths.Clear();
}
rwlock.ExitReadLock();
}
}
void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
try
{
rwlock.EnterWriteLock();
filePaths.Add(e.FullPath);
if (processTimer == null)
{
// First file, start timer.
processTimer = new Timer(2000);
processTimer.Elapsed += (o, ee) => ProcessQueue();
processTimer.Start();
}
else
{
// Subsequent file, reset timer.
processTimer.Stop();
processTimer.Start();
}
}
finally
{
rwlock.ExitWriteLock();
}
}
我不得不将事件触发器移到 finally 语句中,这很有效。我不知道是否有什么理由我不想这样做?
【问题讨论】:
-
您是否会从正在删除/添加文件的目录以及已移动文件的目录中获取事件?如果是这样,也许您可以忽略(或过滤)文件事件而只收听目录事件?编辑:如果添加了多个文件,您可能还会从目录中获得多个添加事件,对吗? ://
-
我不太清楚你在这里问什么。您是否要在代码开始时填充列表,然后等到所有内容都被移动?还是您会逐渐填充列表?
-
@Chris:好吧,假设用户选择了许多文件并将它们移动到另一个子目录。在这种情况下,该事件将为每个文件触发(这将触发删除和创建事件,我正在使用创建事件来检测移动的文件)。因此,即使用户在一次操作中移动的每个文件都会触发事件,但我只想在所有文件都被移动后处理该事件。
-
@Anders:嗯,我不确定我是否完全理解你的问题,我对 FileSystemWatcher 很陌生,但是我认为你说的是正确的,应该有多个两者都触发,所以我不知道如何解决它......
-
啊,好的。看起来杰的答案是要走的路。无论如何,我总是发现文件系统观察器有点不稳定!
标签: c# filesystemwatcher