我正在使用Visual Studio 2012來創建一個包含擴展Windows窗體TreeView窗體的類的.dll。我的自定義TreeView被稱爲FolderTreeView。在它的內部,我添加了一些我需要的私有字段,主要是包含DriveInfo和關聯的FileSystemWatcher的Tuple列表。.net自定義窗體甚至處理程序從不同線程調用並崩潰VS
foreach (var drive in DriveInfo.GetDrives()) { if (drive.IsReady == true) { FileSystemWatcher watcher = new FileSystemWatcher(drive.RootDirectory.FullName); //_drives is List of Tuples _drives.Add(new Tuple<DriveInfo, FileSystemWatcher>(drive, watcher)); watcher.NotifyFilter = NotifyFilters.DirectoryName; watcher.IncludeSubdirectories = true; watcher.Created += new FileSystemEventHandler(FileSystemWatcher_OnCreated); watcher.Changed += new FileSystemEventHandler(FileSystemWatcher_OnChange); watcher.Deleted += new FileSystemEventHandler(FileSystemWatcher_OnDelete); watcher.Renamed += new RenamedEventHandler(FileSystemWatcher_OnRename); watcher.EnableRaisingEvents = true; Nodes.Add(drive.RootDirectory.Name); } }
此代碼會導致兩個問題,我懷疑這兩個問題都是偶處理程序。第一個問題是FileSystemWatcher的事件從另一個線程被調用,所以它會拋出異常,因爲不應允許其他線程訪問Windows窗體。
第二個問題是,如果我爲FileSystemWatcher設置了重命名事件處理程序的代碼沒有被註釋掉,並且我在Windows資源管理器中更改了文件夾名稱,Visual Studio崩潰了,我不知道爲什麼。我好像很可能是由重命名事件處理程序引起的。
我想首先解決線程問題,因爲可能會修復崩潰,除非有另外的原因可能發生。此外,處理所有Filesystem的東西和在不同類中構建節點會更好嗎,只需從該類中獲取一個節點並將其提供給常規TreeView?
編輯:我相信它與線程有關。當它崩潰時,我可以在Visual Studio的另一個實例中進行調試,並且在斷點處獲取空引用異常。這讓我有理由相信事件正在另一個線程中觸發,所以我的斷點沒有被它認爲應該在的線程觸發?
這是正常的,這些事件在線程池線程上引發。導入,因爲需要快速處理事件以避免緩衝區溢出。當您在每個驅動器上聆聽每一個可能的文件更改時,您都會*需要這樣做。非常不明智的是,你甚至無法調用Control.BeginInvoke()來避免異常。 ConcurrentQueue是最低要求。 –
@HansPassant爲TreeView中的每個展開的節點構造一個新的FileSystemWatcher並將IncludeSubDirectories設置爲false並僅監視可見節點會更好嗎?另外,我只監視目錄,如果這有助於緩衝大問題? – contrapsych