这里是完整的源代码:http://pastebin.com/mLaGwwi0 正如您将注意到的,事情是扫描目录和文件并在树视图中填充它们。我正在使用后台工作程序(与Threads类相同)在后台执行此操作,同时逐个更新带有节点的treeview。 问题是它不在后台工作而不更新树视图。这是悬挂形式的代码的一部分:
public void ListDirectory(DirectoryInfo path)
{
treeView1.Nodes.Add(CreateDirectoryNode(path));
}
public void Addnode(DirectoryInfo dirinfo)
{
Invoke(new AddCDAnode(ListDirectory), new object[] { dirinfo });
}
private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
//Statustext = directory.FullName;
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
foreach (var file in directoryInfo.GetFiles())
directoryNode.Nodes.Add(new TreeNode(file.Name));
return directoryNode;
}
public delegate void AddCDAnode(DirectoryInfo dirinfo);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DirectoryInfo dir = new DirectoryInfo(@"\\server\trabajos 2013\");
Addnode(dir);
}
private void Form1_Load(object sender, EventArgs e)
{
//Start filling the TreeView on a separate thread
backgroundWorker1.RunWorkerAsync();
}
在完整源代码中,您将看到注释代码 - 这是来自示例并在后台工作而没有任何麻烦。所以我认为问题在于我的扫描目录代码。
解决方案是also available here,如果您想下载它。
答案 0 :(得分:2)
问题是你启动了一个后台线程,然后立即调用Invoke
来运行UI线程中的所有实际代码,从而阻止了UI线程。
您需要做的是将UI逻辑与非UI逻辑分开。确保在后台线程中执行非UI逻辑,并在UI线程中执行UI逻辑。
在这种情况下,CreateDirectoryNode(path)
基本上都是您的非UI工作。它正在进行大量的文件操作(这非常耗时),并且通常会创建UI稍后将使用的数据。
应该在后台工作人员的DoWork
事件中完成。然后,您可以根据BGW生成的结果设置BGW的Result
属性,以便以后使用。
对于应在treeView1.Nodes.Add(
事件中的RunWorkerCompleted
调用的UI部分。该事件旨在让您根据长时间运行的任务的结果来操作UI。在那里,您可以读取BGW的Result
属性(它是传递给事件处理程序的参数中的属性),并且可以将数据添加到树视图中。由于这是在UI线程中,因此您不会获得跨线程异常,并且由于您在后台线程中完成了长时间运行的文件IO,因此它不会处理UI。
所以你需要的只是你的CreateDirectryNode
方法和以下内容:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DirectoryInfo dir = new DirectoryInfo(@"\\server\trabajos 2013\");
e.Result = CreateDirectoryNode(dir);
}
//TODO ensure that this event handler is added to your BGW so it actually fires
void Form1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
treeView1.Nodes.Add((TreeNode)e.Result);
}