【发布时间】:2011-03-18 22:06:16
【问题描述】:
我正在开发一个解析器应用程序,以根据从数据库中提取的 DDL 文件构建调用树。我们的想法是获取大量这些 DDL 文件并准确确定什么叫什么。为此,我使用了 .NET TreeView。我正在努力的最终输出是这样的:
-Proc1
-Proc2
-Proc3
-Proc4
-Proc2
-Proc3
-Proc3
-Proc4
现在,我的所有解析都正常工作。虽然,这个过程相当漫长。因此,我决定将所有重量级处理转移到它自己的线程上。一切都按预期工作,直到我需要更新 TreeView。我试图将所有实际更新逻辑保留在单独的线程上,并且只更新 TreeView。然而,尽管我的主窗体 SyncLocked,当我尝试访问树时仍然遇到异常。
我在网上找到了很多示例,这些示例展示了如何使用 Delegates 进行线程安全访问,但不幸的是,它们对于我的需求来说都有些简单。大多数只是显示如何设置文本属性。正如我之前提到的,我试图在工作线程上保留尽可能多的处理,并且只调用相应的 TreeView 方法来更新,因为这个过程可能非常冗长(一次解析和显示数百个过程) .
有什么好的方法可以做到这一点,还是我应该只管把我的整个依赖树传递回我的主窗体?
这是我目前用来显示第一级依赖关系的代码。请记住,这最终将是递归的(目前处于“让它工作”模式),这就是为什么我想让它远离 UI 线程:
Public Sub updateTreeView()
Dim arrNodeList As ArrayList
Dim childNode As clsProcedureNode
Dim currentNode As clsProcedureNode
Dim intChildIndex As Integer
Dim intNodeListIndex As Integer
Dim treeView As TreeView
//Lock main form
SyncLock mMainForm
//Check that we are actually running on a seprate thread
If mMainForm.InvokeRequired() = True Then
//Call delegate to get handle to TreeView
treeView = mMainForm.Invoke(mGetTreeViewDelegate)
//Add Parsed array to main form TreeView
For intNodeListIndex = 0 To mProcedureNodes.Length - 1
//Get current node and its child list
currentNode = mProcedureNodes(intNodeListIndex)
arrNodeList = currentNode.getProcsCalled()
//Add node and all children to TreeView
With treeView
.BeginUpdate()
.Nodes.Add(currentNode.getName())
For intChildIndex = 0 To arrNodeList.Count
childNode = arrNodeList.Item(intChildIndex)
.Nodes(intNodeListIndex).Nodes.Add(childNode.getName())
Next
.EndUpdate()
End With
Next
End If
End SyncLock
End Sub
【问题讨论】:
-
您不必在 UI 线程上操作树视图吗?您将树视图拉出主窗体,然后将其填充到线程上。我认为您需要将数据传递回 UI 线程,然后在那里填充。
-
这实际上是我想要避免的。该过程分两个步骤进行。解析 DDL 文件,然后构建树。由于我正在使用的数据集非常大且具有递归性质,我正在尝试在线程外构建树,以便在填充树时 UI 不会挂起。
标签: .net vb.net multithreading design-patterns