JumpyNET Posted November 27, 2005 Posted November 27, 2005 I have a form with one ListBox in it and use the code below. I have allowed drop to the listbox and plan to drop files to it (both folders and files). Files are added at once and folders are searched for more files and subfolders. But when I add a folder containing alot of files like the C-drive then both the program and explorer hang until all files are added. I could prevent the program from hanging by adding Application.DoEvents() here and there but of course it has no effect on explorer. So how can I prevent explorer from hanging? I would like to drag&drop other folders to my app from explorer even when the previous folder had not yeat been fully processed. Private Sub ListBox1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter ' Let's allow files to be dropped. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then e.Effect = DragDropEffects.Copy Else e.Effect = DragDropEffects.None End If End Sub Private Sub ListBox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop ' Accept on files and folders. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then Dim Items() As Object = CType(e.Data.GetData(DataFormats.FileDrop), System.Object) Dim File As Object For Each File In Items ' Let's see if we are dealing with a file or a folder. If System.IO.File.Exists(File) Then ' It's a file, so we add it to the listbox. AddFile(File.ToString) ElseIf System.IO.Directory.Exists(File) Then ' It's a folder, so we must search it for files. FindFiles(File.ToString) End If Next End If End Sub Private Sub AddFile(ByVal FilePath As String) ' Simply add the file to the listbox. ListBox1.Items.Add(FilePath) End Sub Private Sub FindFiles(ByVal Directory As String) ' Find files in current folder. Try Dim Files As String() = System.IO.Directory.GetFiles(Directory, "*") Dim File As String For Each File In Files AddFile(File) Next Catch End Try ' Find subfolders in current folder and search them for files too. Try Dim Dirs As String() = System.IO.Directory.GetDirectories(Directory, "*") Dim Dir As String For Each Dir In Dirs FindFiles(Dir) Next Catch End Try End Sub Quote
JumpyNET Posted November 29, 2005 Author Posted November 29, 2005 Trying... I have been searching some info on threading and found a promising thread by Derek Stone but the links are dead! Threading: Passing Parameters, Returning Values and Accessing Controls http://www.xtremedotnettalk.com/showthread.php?t=70749&highlight=threading+instance So does anyone of you know how to use threads with parameters and access controls from them? I think that could be the answer for my problem. Quote
Wile Posted November 29, 2005 Posted November 29, 2005 The ThreadPool object allows starting a separate thread with a parameter, using the QueueUserWorkItem method, the 2nd overload has two parameters: a WaitCallback delegate (the method to be called on a separate thread), and an object that will be passed to this method. This is a different solution than the one in that post, but there is a decent amount of explanation on msdn for it ;). Search this forum for InvokeRequired for how to access user controls from a different thread. It should return plenty of results ;). Quote Nothing is as illusive as 'the last bug'.
JumpyNET Posted November 29, 2005 Author Posted November 29, 2005 (edited) I came up with this. Do you think there's any bad practise in the code? Imports System.Threading Public Class Form1 Private Sub ListBox1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter ' Let's allow files to be dropped. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then e.Effect = DragDropEffects.Copy Else e.Effect = DragDropEffects.None End If End Sub Private Sub ListBox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop ' Accept files and folders. If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then Dim Items() As Object = CType(e.Data.GetData(DataFormats.FileDrop), System.Object) Dim AddFilesClass As New AddFiles AddFilesClass.AddItems(Items, ListBox1) End If End Sub End Class Public Class AddFiles Private Shared ThreadCount As Integer Private Delegate Sub AddItemDelegate(ByVal FullPath As String, ByVal ListBox As ListBox) Private Delegate Sub StartAddItemsDelegate(ByVal Items() As Object, ByVal ListBox As ListBox) Private Delegate Sub EndAddItemsDelegate(ByVal ThreadName As String) Private Class AddFileArgs Public Items() As Object Public ListBox As ListBox Public StartDelegate As StartAddItemsDelegate Public EndDelegate As EndAddItemsDelegate Public Sub StartAdding() StartDelegate(Items, ListBox) EndDelegate(Thread.CurrentThread.Name) End Sub End Class Private Sub FilesAndFolders(ByVal Items() As Object, ByVal ListBox As ListBox) Dim File As Object For Each File In Items ' Let's see if we are dealing with a file or a folder. If System.IO.File.Exists(File) Then ' It's a file, so we add it to the listbox. If ListBox.InvokeRequired Then ListBox.Invoke(New AddItemDelegate(AddressOf AddFile), New Object() {File.ToString, ListBox}) Else Me.AddFile(File.ToString, ListBox) End If ElseIf System.IO.Directory.Exists(File) Then ' It's a folder, so we must search it for files. AddDirectory(File.ToString, ListBox) End If Next End Sub Private Sub AddFile(ByVal FilePath As String, ByVal ListBox As ListBox) ' Simply add the file to the listbox. ListBox.Items.Add(FilePath) End Sub Private Sub AddDirectory(ByVal Directory As String, ByVal ListBox As ListBox) ' Find files in current folder. Try Dim Files As String() = System.IO.Directory.GetFiles(Directory, "*") Dim File As String For Each File In Files ' Add the file If ListBox.InvokeRequired Then ListBox.Invoke(New AddItemDelegate(AddressOf AddFile), New Object() {File, ListBox}) Else Me.AddFile(File, ListBox) End If Next Catch End Try ' Find subfolders in current folder and search them for files too. Try Dim Dirs As String() = System.IO.Directory.GetDirectories(Directory, "*") Dim Dir As String For Each Dir In Dirs AddDirectory(Dir, ListBox) Next Catch End Try End Sub Private Sub Done(ByVal threadName As String) 'If ListBox1.InvokeRequired Then ' Debug.Print("Done is executing on the launched thread.") 'Else ' Debug.Print("Done is executing on the main thread.") 'End If Debug.Print(threadName & " finished.") End Sub ' *** It all starts here **** Public Sub AddItems(ByVal Items() As Object, ByVal ListBox As ListBox) Dim ca As New AddFiles.AddFileArgs ca.Items = Items ca.ListBox = ListBox ca.StartDelegate = AddressOf FilesAndFolders ca.EndDelegate = AddressOf Done Dim t As New Thread(AddressOf ca.StartAdding) ThreadCount += 1 t.Name = "Thread " & ThreadCount Debug.Print(t.Name & " started.") t.Priority = ThreadPriority.BelowNormal t.IsBackground = True t.Start() End Sub End Class Edited November 29, 2005 by JumpyNET Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.