2009-10-15 26 views
6

FileSystemWatcher không hoạt động đúng khi nhiều tập tin được thêm vào thư mục cùng một lúc ...FileSystemWatcher không hoạt động đúng khi nhiều tập tin được thêm vào thư mục cùng lúc

Các Watcher chỉ đơn giản là không tìm tất cả các tệp trong thư mục - chỉ khi các tệp được đặt trong thư mục từng cái một - không phải nếu nhiều tệp được sao chép vào thư mục cùng một lúc ...

Là việc tạo Chủ đề cho giải pháp vấn đề hoặc là có một cách khác để xử lý vấn đề?

+1

Hãy nhớ rằng FileSystemWatcher dựa trên hệ điều hành để báo hiệu khi tệp được thêm/sửa/xóa/v.v. Vì vậy, có nhiều trường hợp sẽ không giúp ích gì. –

Trả lời

11

Các documentation on that class chi tiết mà vấn đề:

Các hệ điều hành Windows thông báo cho thành phần của bạn thay đổi tập tin trong một bộ đệm tạo ra bởi các FileSystemWatcher. Nếu có nhiều thay đổi trong một thời gian ngắn, bộ đệm có thể tràn. Điều này làm cho thành phần mất theo dõi các thay đổi trong thư mục và nó sẽ chỉ cung cấp thông báo chăn. Tăng kích thước của bộ đệm với thuộc tính InternalBufferSize là tốn kém, vì nó đến từ bộ nhớ không phân trang mà không thể được hoán đổi ra đĩa, vì vậy giữ bộ đệm nhỏ nhưng đủ lớn để không bỏ lỡ bất kỳ sự kiện thay đổi tệp nào. Để tránh tràn bộ đệm, hãy sử dụng các thuộc tính NotifyFilterIncludeSubdirectories để bạn có thể lọc ra các thông báo thay đổi không mong muốn.

Vì vậy, chủ đề có thể sẽ không giúp bạn nhiều trong trường hợp này. Bạn có thể muốn tăng kích thước bộ đệm (nhưng kích thước của nó sẽ lớn như thế nào tùy thuộc vào tốc độ của máy tính và bản thân đĩa) hoặc hạn chế những tệp bạn quan tâm bằng cách đặt bộ lọc thích hợp.

+1

Và, tất nhiên, một tùy chọn khác là để thăm dò ý kiến ​​thêm thư mục cho các tệp mới và tệp đã bị bỏ lỡ. –

+0

Đôi khi tôi đánh giá thấp C#, .Net ... vì sự phát triển trong thế giới của Microsoft rất dễ dàng (bằng cách nói "Microsoft nên nghĩ rằng đối với tôi quá ...") và cư xử cocky vì vậy không đọc tài liệu và sau đó đặt giờ vào những điều nhỏ như thế này lol – sotn

0

hãy thử một cái gì đó như thế này.

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# là mới đối với tôi và tôi gặp khó khăn với cùng một sự cố trong gần một tuần. Tôi đã có điều này:

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

Tôi thậm chí đặt khoảng thời gian hẹn giờ thành 1 mili giây và một số sự kiện tệp mới bị thiếu. Tôi đã cố gắng cập nhật notificationsListBox từ bên trong sự kiện onCreated nhưng tôi luôn gặp lỗi Tham chiếu chéo. Điều này cho đến khi tôi phát hiện ra rằng sự kiện onCreated của người quan sát được thực hiện trong một chủ đề khác với chủ đề chính, do đó, trong vỏ hạt, đây là giải pháp của tôi:

Tôi bao gồm public delegate void Action() làm thuộc tính của tôi và sau đó sử dụng Invoke để cập nhật notificationsListBox từ bên trong sự kiện onCreated. Tiếp theo, mã mẫu:

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

Vì vậy, bộ hẹn giờ và mã của nó không còn cần thiết nữa. Điều này làm việc tuyệt vời cho tôi và tôi hy vọng nó cho bất cứ ai có tình huống tương tự. Trân trọng !!!

Các vấn đề liên quan