问题
I've been working through my first project and have had a great deal a valuable help from the guys on SO but now I'm stuck again.
The below sub is used to add TreeNodes to a TreeView, excluding certain filetypes/names, upon addition of new data:
Sub DirSearch(ByVal strDir As String, ByVal strPattern As String, ByVal tvParent As TreeNodeCollection)
Dim f As String
Dim e As String
Dim tvNode As TreeNode
Dim ext() As String = strPattern.Split("|"c)
Try
For Each d In Directory.GetDirectories(strDir)
If (UCase(IO.Path.GetFileName(d)) <> "BACKUP") And (UCase(IO.Path.GetFileName(d)) <> "BARS") Then
tvNode = tvParent.Add(IO.Path.GetFileName(d))
For Each e In ext
For Each f In Directory.GetFiles(d, e)
If (UCase(IO.Path.GetFileName(f)) <> "DATA.XLS") And (UCase(IO.Path.GetFileName(f)) <> "SPIRIT.XLSX") Then
tvNode.Nodes.Add(IO.Path.GetFileName(f))
End If
Next
Next
DirSearch(d, strPattern, tvNode.Nodes)
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I'm now getting an error:
Action being performed on this control is being called from the wrong thread. Marshal to the correct thread using Control.Invoke or Control.BeginInvoke to perform this action.
On the following line:
tvNode = tvParent.Add(IO.Path.GetFileName(d))
Obviously, I understand its to do with 'threading' and the use of BeginInvoke
/ Invoke
but even after reading the MSDN documentation on the error, I have no idea where to start.
This error only occurs, if I add a file to the initial directory (which is also the subject of a File System Watcher to monitor new additions).
Would someone be so kind as to give me an explanation in layman's terms so I may be able to understand.
回答1:
This code is being run on a background thread where it's illegal to modify UI elements. The Invoke / BeginInvoke
methods are ways to schedule a piece of code to run on UI thread where elements can be modified. For example you could change your code to the following
Dim action As Action = Sub() tvNode.Nodes.Add(IO.Path.GetFileName(f))
tvNode.TreeView.Invoke(action)
This code will take the delegate instance named action
and run it on the UI thread where edits to tvNode
are allowed
Fixing the earlier Add
call is a bit trickier because there is no Control
instance on which we can call BeginInvoke
. The signature of the method will need to be updated to take a Dim control as Control
as a parameter. You can pass in the TreeView
for that parameter if you like. Once that is present the first Add
can be changed as such
Dim outerAction As Action = Sub() tvNode = tvParent.Add(IO.Path.GetFileName(d))
control.Invoke(outerAction)
来源:https://stackoverflow.com/questions/21864281/adding-nodes-to-treeview-with-begin-invoke-invoke