国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

FileSystemWatcher觸發(fā)多次Change事件的解決辦法

2019-11-14 16:38:08
字體:
來源:轉載
供稿:網友

(轉) 

最近要用到FileSystemWatcher來監(jiān)控某個目錄中的文件是否發(fā)生改變,如果改變就執(zhí)行相應的操作(具體操作如:打開文檔,添加一行,保存)。但在開發(fā)過程中,發(fā)現FileSystemWatcher在文件創(chuàng)建或修改后,會觸發(fā)多個Created或Changed事件,具體原因就是處理文件的過程中執(zhí)行了多次文件系統操作,觸發(fā)了多次事件。具體可以參看微軟的關于FileSystemWatcher這方面解釋Troubleshooting FileSystemWatcher Components 另外我在網上發(fā)現 Consolidate Multiple FileSystemWatcher Events 關于這方面的解決辦法,比較實用,方便快速引入到項目中。

來自MSDN的問題說明

Troubleshooting FileSystemWatcher Components

Visual Studio .NET 2003
 
其他版本
 
此主題尚未評級 評價此主題
 

You may encounter the following situations while working with the FileSystemWatcher component:

UNC Path Names Not Accepted on Windows NT 4.0 Computers

If you are working with a FileSystemWatcher component on a Windows NT version 4.0 computer and trying to set its path to monitor file system activity on a different Windows NT version 4.0 computer, you will not be able to specify a UNC-based path value in the Path PRoperty to point to the computer in question. You can only set UNC-based values when working on Windows 2000 computers.

Cannot Watch Windows 95 or Windows 98 Directories

If you set your FileSystemWatcher component to reference a directory on a Windows 95 or Windows 98 computer, you will receive an error about an invalid directory path when the project runs. When using FileSystemWatcher, you cannot watch directories on computers running Windows 95 or Windows 98.

Multiple Created Events Generated for a Single Action

You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use aFileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the Operating system activities, all events that these applications fire will be picked up.

Note   Notepad may also cause other interesting event generations. For example, if you use the ChangeEventFilter to specify that you want to watch only for attribute changes, and then you write to a file in the directory you are watching using Notepad, you will raise an event . This is because Notepad updates theArchived attribute for the file during this operation.

Unexpected Events Generated on Directories

Changing a file within a directory you are monitoring with a FileSystemWatcher component generates not only a Changed event on the file but also a similar event for the directory itself. This is because the directory maintains several types of information for each file it contains — the names and sizes of files, their modification dates, attributes, and so on. Whenever one of these attributes changes, a change is associated with the directory as well.

解決方案

The .NET framework provides a FileSystemWatcher class that can be used to monitor the file system for changes. My requirements were to monitor a directory for new files or changes to existing files. When a change occurs, the application needs to read the file and immediately perform some operation based on the contents of the file.

While doing some manual testing of my initial implementation it was very obvious that theFileSystemWatcher was firing multiple events whenever I made a change to a file or copied a file into the directory being monitored. I came across the following in the MSDNdocumentation’s Troubleshooting FileSystemWatcher Components

Multiple Created Events Generated for a Single Action

You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use a FileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the operating system activities, all events that these applications fire will be picked up.

Note: Notepad may also cause other interesting event generations. For example, if you use the ChangeEventFilter to specify that you want to watch only for attribute changes, and then you write to a file in the directory you are watching using Notepad, you will raise an event. This is because Notepad updates the Archived attribute for the file during this operation.

I did some searching and was surprised that .NET did not provide any kind of wrapper around the FileSystemWatcher to make it a bit more user friendly. I ended up writing my own wrapper that would monitor a directory and only throw one event when a new file was created, or an existing file was changed.

In order to consolidate the multiple FileSystemWatcher events down to a single event, I save the timestamp when each event is received, and I check back every so often (using a Timer) to find paths that have not caused additional events in a while. When one of these paths is ready, a single Changed event is fired. An additional benefit of this technique is that the event from the FileSystemWatcher is handled very quickly, which could help prevent its internal buffer from filling up.

Here is the code for a DirectoryMonitor class that consolidates multiple Win32 events into a single Change event for each change:

解決方案代碼

[csharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.IO;  
  6. using System.Threading;  
  7.   
  8. namespace ShareReadFile  
  9. {  
  10.     public delegate void FileSystemEvent(String path);  
  11.   
  12.     public interface IDirectoryMonitor  
  13.     {  
  14.         event FileSystemEvent Change;  
  15.         void Start();  
  16.     }  
  17.   
  18.     public class DirectoryMonitor : IDirectoryMonitor  
  19.     {  
  20.         private readonly FileSystemWatcher m_fileSystemWatcher = new FileSystemWatcher();  
  21.         private readonly Dictionary<string, DateTime> m_pendingEvents = new Dictionary<string, DateTime>();  
  22.         private readonly Timer m_timer;  
  23.         private bool m_timerStarted = false;  
  24.   
  25.         public DirectoryMonitor(string dirPath)  
  26.         {  
  27.             m_fileSystemWatcher.Path = dirPath;  
  28.             m_fileSystemWatcher.IncludeSubdirectories = false;  
  29.             m_fileSystemWatcher.Created += new FileSystemEventHandler(OnChange);  
  30.             m_fileSystemWatcher.Changed += new FileSystemEventHandler(OnChange);  
  31.   
  32.             m_timer = new Timer(OnTimeout, null, Timeout.Infinite, Timeout.Infinite);  
  33.         }  
  34.   
  35.         public event FileSystemEvent Change;  
  36.   
  37.         public void Start()  
  38.         {  
  39.             m_fileSystemWatcher.EnableRaisingEvents = true;  
  40.         }  
  41.   
  42.         private void OnChange(object sender, FileSystemEventArgs e)  
  43.         {  
  44.             // Don't want other threads messing with the pending events right now  
  45.             lock (m_pendingEvents)  
  46.             {  
  47.                 // Save a timestamp for the most recent event for this path  
  48.                 m_pendingEvents[e.FullPath] = DateTime.Now;  
  49.   
  50.                 // Start a timer if not already started  
  51.                 if (!m_timerStarted)  
  52.                 {  
  53.                     m_timer.Change(100, 100);  
  54.                     m_timerStarted = true;  
  55.                 }  
  56.             }  
  57.         }  
  58.   
  59.         private void OnTimeout(object state)  
  60.         {  
  61.             List<string> paths;  
  62.   
  63.             // Don't want other threads messing with the pending events right now  
  64.             lock (m_pendingEvents)  
  65.             {  
  66.                 // Get a list of all paths that should have events thrown  
  67.                 paths = FindReadyPaths(m_pendingEvents);  
  68.   
  69.                 // Remove paths that are going to be used now  
  70.                 paths.ForEach(delegate(string path)  
  71.                 {  
  72.                     m_pendingEvents.Remove(path);  
  73.                 });  
  74.   
  75.                 // Stop the timer if there are no more events pending  
  76.                 if (m_pendingEvents.Count == 0)  
  77.                 {  
  78.                     m_timer.Change(Timeout.Infinite, Timeout.Infinite);  
  79.                     m_timerStarted = false;  
  80.                 }  
  81.             }  
  82.   
  83.             // Fire an event for each path that has changed  
  84.             paths.ForEach(delegate(string path)  
  85.             {  
  86.                 FireEvent(path);  
  87.             });  
  88.         }  
  89.   
  90.         private List<string> FindReadyPaths(Dictionary<string, DateTime> events)  
  91.         {  
  92.             List<string> results = new List<string>();  
  93.             DateTime now = DateTime.Now;  
  94.   
  95.             foreach (KeyValuePair<string, DateTime> entry in events)  
  96.             {  
  97.                 // If the path has not received a new event in the last 75ms  
  98.                 // an event for the path should be fired  
  99.                 double diff = now.Subtract(entry.Value).TotalMilliseconds;  
  100.                 if (diff >= 75)  
  101.                 {  
  102.                     results.Add(entry.Key);  
  103.                 }  
  104.             }  
  105.   
  106.             return results;  
  107.         }  
  108.   
  109.         private void FireEvent(string path)  
  110.         {  
  111.             FileSystemEvent evt = Change;  
  112.             if (evt != null)  
  113.             {  
  114.                 evt(path);  
  115.             }  
  116.         }  
  117.     }  
  118. }  

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 广水市| 汝阳县| 民权县| 莱阳市| 三都| 长沙县| 石台县| 鄂托克旗| 镇巴县| 榆中县| 莱西市| 高安市| 同德县| 松江区| 湟源县| 洪洞县| 白玉县| 萍乡市| 横山县| 延边| 五原县| 双辽市| 岢岚县| 徐汇区| 和林格尔县| 西贡区| 招远市| 沁源县| 马龙县| 怀集县| 宜兴市| 文山县| 开平市| 湘西| 宝丰县| 珠海市| 宁远县| 云浮市| 昆山市| 盘锦市| 观塘区|