当目录中同时添加很多文件时FileSystemWatcher无法正常工作

发布于 2024-08-07 16:26:05 字数 159 浏览 7 评论 0原文

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

Watcher 根本找不到目录中的所有文件 - 仅当文件被一一放入文件夹中时 - 如果文件很多则不会文件同时复制到该文件夹​​...

创建线程是问题的解决方案还是有其他方法来处理问题?

FileSystemWatcher does not work properly when many files are added to the directory at the same time...

The Watcher simply doesn't find all the files in the directory - only if the files are placed in the folder one by one - not if lots of files are copied to the folder at the same time...

Is the creation of Threads the solution to the problem or is there another way to handle the problem ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

飘然心甜 2024-08-14 16:26:05

该类的文档详细介绍了该问题:

Windows 操作系统会通知您的组件由 FileSystemWatcher 创建的缓冲区中的文件更改。如果短时间内发生多次变化,缓冲区可能会溢出。这会导致组件失去对目录中更改的跟踪,并且它只会提供全面通知。使用 InternalBufferSize 增加缓冲区的大小属性很昂贵,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区足够小但足够大,以免错过任何文件更改事件。为了避免缓冲区溢出,请使用 NotifyFilterIncludeSubdirectories 属性,以便您可以过滤掉不需要的更改通知。

因此,在这种情况下,线程可能不会有太大帮助。您可能想要增加缓冲区大小(但它应该有多大可能很大程度上取决于计算机和磁盘本身的速度)或通过设置适当的过滤器来限制您感兴趣的文件。

The documentation on that class details that problem:

The Windows operating system notifies your component of file changes in a buffer created by the FileSystemWatcher. If there are many changes in a short time, the buffer can overflow. This causes the component to lose track of changes in the directory, and it will only provide blanket notification. Increasing the size of the buffer with the InternalBufferSize property is expensive, as it comes from non-paged memory that cannot be swapped out to disk, so keep the buffer as small yet large enough to not miss any file change events. To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties so you can filter out unwanted change notifications.

So, threads probably won't help you much in this case. You probably want to either increase the buffer size (but how large it should be may well depend on the speed of the computer and the disk itself) or constrain what files you are interested in by setting the appropriate filter.

献世佛 2024-08-14 16:26:05

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 毫秒,但缺少一些新文件事件。我尝试从 onCreated 事件内部更新 notificationsListBox,但总是收到交叉引用错误。直到我发现观察者 onCreated 事件是在主方法线程之外的线程中执行的,所以,简而言之,这就是我的解决方案:

我包括 public delegate void Action() 作为我的类的属性,然后使用 InvokeonCreated 事件内部更新 notificationsListBox 。接下来是片段代码:

    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());}));
    }

因此不再需要计时器及其代码。
这对我来说非常有效,我希望它对任何有类似情况的人都有效。
此致!!!

C# is new to me and I struggled with the same trouble for nearly a week. I had this:

    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;
        }
    }

I even set the timer interval to 1 millisecond and yet some new file events were missing. I tried to update the notificationsListBox from inside the onCreated event but I always got a Cross-reference error. This was until I found out that the watcher onCreated event is executed in a thread other than the one of the main method thread, so, in a nut shell, this is my solution:

I included public delegate void Action() as an attribute of my class and then used Invoke to update the notificationsListBox from inside the onCreated event. Next, the piece code:

    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());}));
    }

So the timer and its code are no longer necessary.
This works excellent for me and I hope it does for anyone with a similar situation.
Best regards!!!

酷遇一生 2024-08-14 16:26:05

尝试这样的事情。

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);
    }

try something like this.

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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文