使用 FileSystemWatcher 从 TreeView 中删除子节点,出现 "Cross-thread operation not valid" 错误
Using FileSystemWatcher to delete Childnode from TreeView, getting "Cross-thread operation not valid" error
设置 FileSystemWatcher 以更新 TreeView 以反映磁盘目录中的文件。它按预期触发并通过 TreeView returns 搜索正确的节点,但是当我发出 nodeToDelete.Remove() 命令时,出现以下错误:
'System.InvalidOperationException' 类型的未处理异常发生在 System.Windows.Forms.dll
附加信息:跨线程操作无效:控制“_tvwFiles”从创建它的线程以外的线程访问。
我没有意识到我使用了多个线程。关于如何解决这个问题的任何建议?或者也许是一种不同的方式来访问子节点以将其删除?
代码如下:
using System;
using System.IO;
using System.Windows.Forms;
namespace WaveManager
{
public partial class FileViewControl : UserControl
{
public FileViewControl()
{
InitializeComponent();
}
private FileSystemWatcher _watcher;
private const string path = @"c:\temp";
public void OnWaveOpen(string fileName)
{
string filePath = Path.GetDirectoryName(fileName);
TreeNode folderNode;
_tvwFiles.ImageIndex = 0;
_tvwFiles.SelectedImageIndex = 0;
DirectoryInfo directoryInfo = new DirectoryInfo(filePath);
//folderNode = new TreeNode(directoryInfo.Name);
folderNode = new TreeNode(filePath);
folderNode.Tag = directoryInfo;
//Getfiles
TreeNode waveNode;
foreach (FileInfo wavefile in directoryInfo.GetFiles("*.wav"))
{
waveNode = new TreeNode(wavefile.Name, 1, 1);
waveNode.Name = waveNode.Text;
waveNode.Tag = wavefile;
folderNode.Nodes.Add(waveNode);
}
_tvwFiles.Nodes.Add(folderNode);
_tvwFiles.ExpandAll();
}
private void OnLoad(object sender, System.EventArgs e)
{
if (DesignMode)
return;
_tvwFiles.ExpandAll();
_watcher = new FileSystemWatcher(path);
_watcher.EnableRaisingEvents = true;
_watcher.Deleted += OnFileDeleted;
}
private TreeNode FindNodeByTagText(String s, TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Tag.ToString() == s)
return node;
TreeNode n = FindNodeByTagText(s, node.Nodes);
if (n != null)
return n;
}
return null;
}
void OnFileDeleted(object sender, FileSystemEventArgs e)
{
string fn = Path.GetFileName(e.FullPath);
TreeNode nodeToDelete = FindNodeByTagText(fn, _tvwFiles.Nodes);
nodeToDelete.Remove();
}
}
}
如有任何想法,我们将不胜感激。谢谢!
我记得(我可能弄错了,现在无法检查)FileSystemWatcher 在内部使用 ThreadPool。也许这就是你得到例外的原因。
尝试设置
_watcher.SynchronizingObject = this;
设置 FileSystemWatcher 以更新 TreeView 以反映磁盘目录中的文件。它按预期触发并通过 TreeView returns 搜索正确的节点,但是当我发出 nodeToDelete.Remove() 命令时,出现以下错误:
'System.InvalidOperationException' 类型的未处理异常发生在 System.Windows.Forms.dll
附加信息:跨线程操作无效:控制“_tvwFiles”从创建它的线程以外的线程访问。
我没有意识到我使用了多个线程。关于如何解决这个问题的任何建议?或者也许是一种不同的方式来访问子节点以将其删除?
代码如下:
using System;
using System.IO;
using System.Windows.Forms;
namespace WaveManager
{
public partial class FileViewControl : UserControl
{
public FileViewControl()
{
InitializeComponent();
}
private FileSystemWatcher _watcher;
private const string path = @"c:\temp";
public void OnWaveOpen(string fileName)
{
string filePath = Path.GetDirectoryName(fileName);
TreeNode folderNode;
_tvwFiles.ImageIndex = 0;
_tvwFiles.SelectedImageIndex = 0;
DirectoryInfo directoryInfo = new DirectoryInfo(filePath);
//folderNode = new TreeNode(directoryInfo.Name);
folderNode = new TreeNode(filePath);
folderNode.Tag = directoryInfo;
//Getfiles
TreeNode waveNode;
foreach (FileInfo wavefile in directoryInfo.GetFiles("*.wav"))
{
waveNode = new TreeNode(wavefile.Name, 1, 1);
waveNode.Name = waveNode.Text;
waveNode.Tag = wavefile;
folderNode.Nodes.Add(waveNode);
}
_tvwFiles.Nodes.Add(folderNode);
_tvwFiles.ExpandAll();
}
private void OnLoad(object sender, System.EventArgs e)
{
if (DesignMode)
return;
_tvwFiles.ExpandAll();
_watcher = new FileSystemWatcher(path);
_watcher.EnableRaisingEvents = true;
_watcher.Deleted += OnFileDeleted;
}
private TreeNode FindNodeByTagText(String s, TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Tag.ToString() == s)
return node;
TreeNode n = FindNodeByTagText(s, node.Nodes);
if (n != null)
return n;
}
return null;
}
void OnFileDeleted(object sender, FileSystemEventArgs e)
{
string fn = Path.GetFileName(e.FullPath);
TreeNode nodeToDelete = FindNodeByTagText(fn, _tvwFiles.Nodes);
nodeToDelete.Remove();
}
}
}
如有任何想法,我们将不胜感激。谢谢!
我记得(我可能弄错了,现在无法检查)FileSystemWatcher 在内部使用 ThreadPool。也许这就是你得到例外的原因。
尝试设置
_watcher.SynchronizingObject = this;