Post date: Feb 7, 2012 3:53:25 PM
TreeView su Multithreading
Uno degli scenari in cui si utilizza un TreeView (vista gerarchica) è per caricare file da cartelle diverse. Immaginiamo di dover caricare molti file che occupano diversi GB nel nostro HD. Popolare un TreeView può richiedere alcuni minuti. Per non aspettare inutilmente è possibile eseguire il caricamento del TreeView in un thread separato. In questa tecnica ci viene in aiuto il multithreading per lavorare su un altro processo, in parallelo.
Quando si lavora su controlli Windows Form in un ambiente multithreading, la condivisione delle risorse tra diversi processi, se non si fa attenzione, può generare un'eccezione.
Nello scenario attuale, se un TreeView viene aggiornato in un thread separato, questo risiederà nel thread principale e i nodi verranno aggiunti in fili consecutivi. Ecco perché le risorse di condivisione devono essere impostate correttamente. Per comunicare da un thread a un altro si può usare Invoke.
TreeView1.Invoke (UpdateTreeDelegate, New Object () {FileInCurrentPath, CurrentNode})
Come nel segmento di codice precedente, il richiamo può essere utilizzato insieme con un delegate. Il delegate punta a una funzione che assolve il compito di accettare gli argomenti denominati FileInCurrentPath, CurrentNode.
Codice esempio - Prelevato da: http://www.dotnetperls.com/vb (En)
Imports System.Threading
Public Class Form1
Dim FilePath
Dim FolderNode As TreeNode
Delegate Function UpdateTree(ByVal nodeName As String, ByVal CurrentNode As TreeNode) As TreeNode
Public UpdateTreeDelegate As UpdateTree
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
FilePath = "D:\Pons\bck"
UpdateTreeDelegate = New UpdateTree(AddressOf AddNode)
FolderNode = TreeView1.Nodes.Add("Projects")
FolderNode.ExpandAll()
Dim thre As New Thread(New ThreadStart(AddressOf LoadTreeView))
thre.Start()
LoadListBox(FilePath)
'LoadTreeView()
End Sub
Private Sub LoadTreeView()
LoadTreeView(FilePath, FolderNode)
End Sub
Private Sub LoadTreeView(ByVal CurrentPath As String, ByVal CurrentNode As TreeNode)
For Each FileInCurrentPath In My.Computer.FileSystem.GetFiles(CurrentPath)
TreeView1.Invoke(UpdateTreeDelegate, New Object() {FileInCurrentPath, CurrentNode})
Application.DoEvents()
Next
For Each FolderInCurrentPath In My.Computer.FileSystem.GetDirectories(CurrentPath)
Dim FolderNode = DirectCast(TreeView1.Invoke(UpdateTreeDelegate, New Object() {FolderInCurrentPath, CurrentNode}), TreeNode)
LoadTreeView(FolderInCurrentPath, FolderNode)
Next
End Sub
Private Function AddNode(ByVal nodeName As String, ByVal CurrentNode As TreeNode) As TreeNode
Return CurrentNode.Nodes.Add(nodeName)
End Function
Private Sub LoadListBox(ByVal CurrentPath As String)
For Each FileInCurrentPath In My.Computer.FileSystem.GetFiles(CurrentPath)
ListBox1.Items.Add(FileInCurrentPath)
Application.DoEvents()
Label1.Text = "file added " + FileInCurrentPath
Next
For Each FolderInCurrentPath In My.Computer.FileSystem.GetDirectories(CurrentPath)
ListBox1.Items.Add(FolderInCurrentPath)
LoadListBox(FolderInCurrentPath)
Next
End Sub
End Class