C# 对多个文件使用FileSystemWatcher
我想使用FileSystemWatcher监视目录及其子目录中被移动的文件。然后我想在所有文件都被移动后触发一些代码。但我不知道怎么做。我的代码将在每次移动文件时触发,如果用户同时移动多个文件,我只希望对所有文件触发一次。所以基本上我想创建一个列表,一旦所有文件的移动完成,我想对这个列表做一些事情 代码如下:C# 对多个文件使用FileSystemWatcher,c#,filesystemwatcher,C#,Filesystemwatcher,我想使用FileSystemWatcher监视目录及其子目录中被移动的文件。然后我想在所有文件都被移动后触发一些代码。但我不知道怎么做。我的代码将在每次移动文件时触发,如果用户同时移动多个文件,我只希望对所有文件触发一次。所以基本上我想创建一个列表,一旦所有文件的移动完成,我想对这个列表做一些事情 代码如下: class Monitor { private List<string> _filePaths; public void CreateWatcher(str
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!");
}
}
类监视器
{
私有列表文件路径;
公共void CreateWatcher(字符串路径)
{
FileSystemWatcher watcher=新的FileSystemWatcher();
watcher.Filter=“***”;
watcher.Created+=新建
FileSystemEventHandler(创建了观察者文件);
watcher.Path=Path;
watcher.IncludeSubdirectories=true;
watcher.EnableRaisingEvents=true;
}
void watcher_FileCreated(对象发送方、文件系统目标)
{
_添加(例如FullPath);
WriteLine(“文件已创建或移动!”);
}
}
更新:尝试使用Chris的代码,但不起作用(请参阅我对Chris答案的评论):
类监视器
{
私有列表文件路径;
专用定时器_通知定时器;
私有文件系统监视程序(fsw);
公共监视器(字符串路径)
{
_notificationTimer=新计时器();
_notificationTimer.Appeased+=notificationTimer\u Appeased;
//CooldownSeconds是每次添加文件时计时器“扩展”的秒数。
//我发现将此值放入应用程序配置文件很方便。
int CooldownSeconds=1;
_notificationTimer.Interval=冷却时间秒*1000;
_fsw=newfilesystemwatcher();
_fsw.Path=Path;
_fsw.IncludeSubdirectories=true;
_fsw.EnableRaisingEvents=true;
//设置文件系统监视程序的详细信息。
_fsw.Created+=fsw_Created;
}
私有无效通知计时器(对象发送方,ElapsedEventArgs e)
{
//
//对文件列表执行您想执行的操作。
//
控制台。写入(“完成”);
//停止计时器并等待下一批文件。
_notificationTimer.Stop();
//清除您的文件列表。
_filepath=新列表();
}
//创建文件时激发。
已创建私有无效fsw_(对象发送方、文件系统目标)
{
//添加到我们的文件列表中。
_filepath.Add(例如Name);
//“重置”计时器。
_notificationTimer.Stop();
_notificationTimer.Start();
}
}
更新2:
根据安德斯的回答,我试过:
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();
}
}
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();
}
}
公共类文件ListEventTargets:EventArgs
{
公共列表文件列表{get;set;}
}
公共班长
{
私有列表文件路径;
私有读写器锁;
专用定时器;
公共事件事件处理程序FileListCreated;
已创建公共无效OnFileListCreated(FileListEventTargets e)
{
如果(FileListCreated!=null)
创建的文件列表(此,e);
}
公共监视器(字符串路径)
{
filepath=新列表();
rBlock=新的ReaderWriterLockSlim();
FileSystemWatcher watcher=新的FileSystemWatcher();
watcher.Filter=“***”;
watcher.Created+=watcher\u FileCreated;
watcher.Path=Path;
watcher.IncludeSubdirectories=true;
watcher.EnableRaisingEvents=true;
}
私有void ProcessQueue()
{
列表=新列表();
尝试
{
Console.WriteLine(“处理队列,”+filepath.Count+“创建的文件:”);
rwlock.EnterReadLock();
}
最后
{
if(processTimer!=null)
{
processTimer.Stop();
processTimer.Dispose();
processTimer=null;
OnFileListCreated(新的FileListEventTargets{FileList=FilePath});
filepath.Clear();
}
rwlock.exitradlock();
}
}
void watcher_FileCreated(对象发送方、文件系统目标)
{
尝试
{
rBlock.EnterWriteLock();
添加(例如FullPath);
if(processTimer==null)
{
//第一个文件,启动计时器。
processTimer=新计时器(2000);
processTimer.Appead+=(o,ee)=>ProcessQueue();
processTimer.Start();
}
其他的
{
//后续文件,重置计时器。
processTimer.Stop();
processTimer.Start();
}
}
最后
{
rBlock.ExitWriteLock();
}
}
我必须将事件触发器移动到finally语句中,这样做是有效的。我不知道是否有什么原因我不想这样做?我必须做完全相同的事情。在监视器类中使用System.Timers.Timer并对其经过的事件进行编码,以处理文件列表并清除列表。当第一项添加到file列表通过FSW事件启动计时器。当后续项目添加到列表中时,通过停止并重新启动计时器来“重置”计时器 大概是这样的:
class Monitor
{
FileSystemWatcher _fsw;
Timer _notificationTimer;
List<string> _filePaths = new List<string>();
public Monitor() {
_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.
_notificationTimer.Interval = CooldownSeconds * 1000;
_fsw = new FileSystemWatcher();
// 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.
//
// 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();
}
}
类监视器
{
文件系统监视程序_fsw;
定时器通知定时器;
列表_filepath=新列表();
公共监督员(){
_notificationTimer=新计时器();
_notificationTimer.Appeased+=notificationTimer\u Appeased;
//CooldownSeconds是每次添加文件时计时器“扩展”的秒数。
//我发现将此值放入应用程序配置文件很方便。
_notificationTimer.Interval=冷却下降秒
public class Monitor : IDisposable
{
private List<string> filePaths;
private ReaderWriterLockSlim rwlock;
private Timer processTimer;
private string watchedPath;
private FileSystemWatcher watcher;
public Monitor(string watchedPath)
{
filePaths = new List<string>();
rwlock = new ReaderWriterLockSlim();
this.watchedPath = watchedPath;
InitFileSystemWatcher();
}
private void InitFileSystemWatcher()
{
watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += Watcher_FileCreated;
watcher.Error += Watcher_Error;
watcher.Path = watchedPath;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
private void Watcher_Error(object sender, ErrorEventArgs e)
{
// Watcher crashed. Re-init.
InitFileSystemWatcher();
}
private 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 += ProcessQueue;
processTimer.Start();
}
else
{
// Subsequent file, reset timer.
processTimer.Stop();
processTimer.Start();
}
}
finally
{
rwlock.ExitWriteLock();
}
}
private void ProcessQueue(object sender, ElapsedEventArgs args)
{
try
{
Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
rwlock.EnterReadLock();
foreach (string filePath in filePaths)
{
Console.WriteLine(filePath);
}
filePaths.Clear();
}
finally
{
if (processTimer != null)
{
processTimer.Stop();
processTimer.Dispose();
processTimer = null;
}
rwlock.ExitReadLock();
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (rwlock != null)
{
rwlock.Dispose();
rwlock = null;
}
if (watcher != null)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose();
watcher = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class Files
{
public static FileSystemWatcher WatchForChanges(string path, string filter, Action triggeredAction)
{
var monitor = new FileSystemWatcher(path, filter);
//monitor.NotifyFilter = NotifyFilters.FileName;
monitor.Changed += (o, e) => triggeredAction.Invoke();
monitor.Created += (o, e) => triggeredAction.Invoke();
monitor.Renamed += (o, e) => triggeredAction.Invoke();
monitor.EnableRaisingEvents = true;
return monitor;
}
}
public IObservable<Unit> OnUpdate(string path, string pattern)
{
return Observable.Create<Unit>(o =>
{
var watcher = Files.WatchForChanges(path, pattern, () => o.OnNext(new Unit()));
return watcher;
});
}
OnUpdate(path, "*.*").Throttle(Timespan.FromSeconds(10)).Subscribe(this, _ => DoWork())