2009-10-15 50 views
6

FileSystemWatcher对象无法正常使用被添加到目录FileSystemWatcher对象无法正常使用......当许多文件在同一时间,当许多文件添加到在同一时间目录

看守人根本不找到目录中的所有文件 - 只有当文件一个接一个地放入文件夹中时 - 并非在同一时间将大量文件复制到文件夹中...

是否创建了线程解决方案问题还是有另一种解决问题的方法?

+1

请记住,FileSystemWatcher依靠操作系统发出信号,当文件被添加/修改/删除/等。所以有多个实例是不会有帮助的。 – 2009-10-15 13:46:37

回答

11

documentation on that class细节问题:

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

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

+1

而且,当然,另一种选择是另外轮询该文件夹以找出错过的新文件和文件。 – 2009-10-15 14:05:35

+0

我有时会低估C#,.Net等,因为微软世界中的开发很容易(通过说“微软应该也认为对我来说......”)并表现自大,所以不要阅读文档,然后把小时放入小东西像这一个大声笑 – sotn 2017-02-01 13:50:34

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); 
    } 
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毫秒,但一些新的文件事件丢失。我试图从onCreated事件中更新notificationsListBox,但我总是收到交叉引用错误。直到我发现观察者onCreated事件在主要方法线程之外的线程中执行,因此,在坚果壳中,这是我的解决方案:

我包含public delegate void Action()作为我的属性然后使用Invoke更新onCreated事件中的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());})); 
    } 

因此,计时器及其代码不再需要。 这对我来说非常适用,我希望它适用于任何有类似情况的人。 祝你好运!

相关问题