我需要在我将使用FileSystemWatcher
的文件夹中记录文件的创建或复制/移动事件。问题是,当我在文件夹中粘贴一个文件时,FileSystemWatcher
将引发一个Created事件。因此,如果我将10
文件集中粘贴到该文件夹中,则会由FileSystemWatcher引发10个事件。我的要求是,如果同时复制它们,则只为文件夹中粘贴的所有10个文件引发一个事件。
请建议。下面是我在MSDN教程的帮助下编写的代码。
public class FileSystemWatcherUtil2
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
/* creation of a new FileSystemWatcher and set its properties */
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"C:\Users\TestFolder";
/*watch for internal folder changes also*/
watcher.IncludeSubdirectories = true;
/* Watch for changes in LastAccess and LastWrite times, and the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
/* event handlers */
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
/* watching started */
watcher.EnableRaisingEvents = true;
/* user should quit the program to stop watching*/
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
/* event handlers definition for changed and renamed */
private static void OnChanged(object source, FileSystemEventArgs e)
{
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
}
答案 0 :(得分:2)
我们的想法是为FileSystemWatcher
实现一个包装器,它会公开自己的CreatedEx
事件,该事件将模拟FileSystemWatcher.Created
事件,但每10个Created
事件发生时会增加一次。但请记住,我们无法确定在单个复制/移动操作的范围内引发所有处理程序Created
事件。为了提高这种方法的可靠性,我建议设置一个DirectoryName NotifyFilters value
,这样你就可以观察到一个目录,但肯定是符合你的要求。也许通过提供有关需求的更多细节,我们可以提供更多细节,因此方法会更可靠,基本上最重要的是确定批量复制/移动操作的常见范围,所以当你复制100个文件和int时同时由OS启动的其他复制操作正在进行中,您需要从您感兴趣的前一操作中过滤掉它。所以可能是文件的一些常用标准等。
FileSystemWatcher
CreatedEx
活动FileSystemWatcher.Created
事件,并在处理程序中启动一个计时器,例如200ms。如果未引发FileSystemWatcher.Created
事件 - 引发自己的CreatedEx
事件,否则重置计时器并等待200毫秒。您可以通过实验方式确定的计时器周期,只需复制不同大小的多个文件,并查看哪个超时足够。
如果你需要为同时发生的10个事件发生一次CreatedEx
事件 - 你可以在FileSystemWatcher.Created
事件处理程序中引入简单的计数器和减量,并在counter==0
时引发自己{ {1}}事件。
答案 1 :(得分:1)
FileSystemWatcher无法知道复制是否作为一个操作完成,因为不存在同时复制多个文件的事情。通过使用拖放,Windows资源管理器看起来就是这样,但它本质上是多个副本。
如果你想要,你可以在FileSystemWatcher周围编写一个简单的包装器来接受所有的Create事件,如果它们发生,比如相隔200ms,则引发一个“Multiple Created”事件。
这是一个监视Create事件的工作代码。如果需要和/或公开其他属性,您可以将其包装在其上以监视其他事件。
public class MyWatcher
{
private FileSystemWatcher watcher = new FileSystemWatcher();
private System.Timers.Timer timer;
private object listSync = new object();
private List<FileSystemEventArgs> events = new List<FileSystemEventArgs>();
public delegate void FileSystemMultipleEventHandler(object sender, FileSystemEventArgs[] events);
public FileSystemMultipleEventHandler OnMultipleFilesCreated { get; set; }
public MyWatcher(string path, NotifyFilters notifyFilters, string filter)
{
this.watcher.Path = path;
this.watcher.Created += FileCreated;
watcher.Filter = filter;
watcher.EnableRaisingEvents = true;
}
private void FileCreated(object sender, FileSystemEventArgs e)
{
if (this.timer != null)
{
this.timer.Stop();
lock (this.listSync) this.events.Add(e);
this.timer.Start();
}
else
{
lock (this.listSync) this.events.Add(e);
this.timer = new Timer(200);
this.timer.Elapsed += MultipleFilesCreated;
this.timer.Start();
}
}
private void MultipleFilesCreated(object stat, ElapsedEventArgs args)
{
if (OnMultipleFilesCreated != null)
{
FileSystemEventArgs[] result;
lock (this.listSync)
{
// make a copy
result = events.ToArray();
this.events = new List<FileSystemEventArgs>();
}
OnMultipleFilesCreated(this, result);
}
this.timer.Stop();
}
}
我在这里使用锁定来访问线程安全的事件列表(timer vs FileCreated事件)。不使用任何并发集合,因为它们没有ClearAll(),我需要逐个锁定和删除项目或者使用锁重新创建集合。