当许多文件同时添加到目录中时,FileSystemWatcher无法正常工作......
Watcher根本找不到目录中的所有文件 - 只有文件一个接一个地放在文件夹中 - 而不是同时将大量文件复制到文件夹中......
Threads的创建是问题的解决方案还是有另一种方法来处理问题?
答案 0 :(得分:12)
documentation on that class详述了问题:
Windows操作系统会在FileSystemWatcher创建的缓冲区中通知组件文件更改。如果在短时间内有许多变化,缓冲区可能会溢出。这会导致组件无法跟踪目录中的更改,并且只会提供一揽子通知。使用InternalBufferSize属性增加缓冲区的大小是非常昂贵的,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区小而大到足以不丢失任何文件更改事件。要避免缓冲区溢出,请使用NotifyFilter和IncludeSubdirectories属性,以便过滤掉不需要的更改通知。
因此,在这种情况下,线程可能对你没什么帮助。您可能想要增加缓冲区大小(但它应该多大可能取决于计算机和磁盘本身的速度)或者通过设置适当的过滤器来约束您感兴趣的文件。
答案 1 :(得分:1)
private void btnWatchFile_Click(object sender, EventArgs e)
{
//code to create a watcher and allow it to reise events...
}
//watcher onCreate event
public void onCreated(object sender, FileSystemEventArgs e)
{
if (!updateNotifications )
{
stringBuilder.Remove(0, stringBuilder.Length);
stringBuilder.Append(e.FullPath);
stringBuilder.Append(" ");
stringBuilder.Append(e.ChangeType.ToString());
stringBuilder.Append(" ");
stringBuilder.Append(DateTime.Now.ToString());
updateNotifications = true;
}
}
//timer to check the flag every X time
private void timer_Tick(object sender, EventArgs e)
{
if (updateNotifications )
{
notificationListBox.Items.Insert(0, stringBuilder.ToString());
updateNotifications = false;
}
}
我甚至将计时器间隔设置为1毫秒,但是缺少一些新的文件事件。我尝试从notificationsListBox
事件中更新onCreated
,但我总是遇到交叉引用错误。直到我发现观察者onCreated
事件是在一个主要方法线程之外的线程中执行的,所以,在坚果壳中,这是我的解决方案:
我将public delegate void Action()
作为我班级的属性,然后使用Invoke
从notificationsListBox
事件中更新onCreated
。接下来,件代码:
public void onCreated(object sender, FileSystemEventArgs e)
{
stringBuilder.Remove(0, stringBuilder.Length);
stringBuilder.Append(e.FullPath);
stringBuilder.Append(" ");
stringBuilder.Append(e.ChangeType.ToString());
stringBuilder.Append(" ");
stringBuilder.Append(DateTime.Now.ToString());
updateNotifications = true;
Invoke((Action)(() => {notificationListBox.Items.Insert(0, stringBuilder.ToString());}));
}
因此不再需要计时器及其代码。 这对我来说非常好,我希望它适用于任何有类似情况的人。 最好的问候!!!
答案 2 :(得分:0)
尝试这样的事情。
public MainWindow()
{
InitializeComponent();
#region initialise FileSystemWatcher
FileSystemWatcher watch = new FileSystemWatcher();
watch.Path = folder;
watch.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
watch.Filter = ext;
watch.Changed += new FileSystemEventHandler(OnChanged);
watch.Created += new FileSystemEventHandler(OnChanged);
watch.EnableRaisingEvents = true;
#endregion
}
private void OnChanged(object source, FileSystemEventArgs e)
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate
{
// do your work here. If this work needs more time than it can be processed, not the filesystembuffer overflows but your application will block. In this case try to improve performance here.
}, System.Windows.Threading.DispatcherPriority.Normal);
}