当许多文件同时添加到目录时,FileSystemWatcher无法正常工作

时间:2009-10-15 13:43:33

标签: c# filesystemwatcher

当许多文件同时添加到目录中时,FileSystemWatcher无法正常工作......

Watcher根本找不到目录中的所有文件 - 只有文件一个接一个地放在文件夹中 - 而不是同时将大量文件复制到文件夹中......

Threads的创建是问题的解决方案还是有另一种方法来处理问题?

3 个答案:

答案 0 :(得分:12)

documentation on that class详述了问题:

  

Windows操作系统会在FileSystemWatcher创建的缓冲区中通知组件文件更改。如果在短时间内有许多变化,缓冲区可能会溢出。这会导致组件无法跟踪目录中的更改,并且只会提供一揽子通知。使用InternalBufferSize属性增加缓冲区的大小是非常昂贵的,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区小而大到足以不丢失任何文件更改事件。要避免缓冲区溢出,请使用NotifyFilterIncludeSubdirectories属性,以便过滤掉不需要的更改通知。

因此,在这种情况下,线程可能对你没什么帮助。您可能想要增加缓冲区大小(但它应该多大可能取决于计算机和磁盘本身的速度)或者通过设置适当的过滤器来约束您感兴趣的文件。

答案 1 :(得分:1)

C#对我来说是新的,我在同样的麻烦中挣扎了近一个星期。我有这个:

    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()作为我班级的属性,然后使用InvokenotificationsListBox事件中更新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);
    }