I've run into a little issue with a simple file copying application I'm writing in Visual Basic 2005. I have a main thread which looks after the GUI, and for the file scanning/copying I've created a separate thread which I create like this:
trd_copy = New Thread(AddressOf CopyTask)
trd_copy.IsBackground = True
trd_copy.Start()
This works fine for the scanning phase of the operation, and I can use the buttons in the GUI just fine. The problem is that when CopyTask gets to the file copying phase (using File.Copy), the main thread appears to lock up, and the GUI with it, meaning that the button I have there for aborting the copy operation is useless. When the copying is done, all returns to normal, and during copying the sub thread can update the status bar on the main form.
I'm sure I'm missing something simple, but I can't for the life of me see what it is.
Thanks very much!
Edit: Adding the code for CopyTask():
Private Sub CopyTask()
Control.CheckForIllegalCrossThreadCalls = False
If check_scanfirst.Checked Then
status1.Text = "Scanning..."
bytestocopy = 0
scandir(src)
filesscanned = True
MsgBox("Scanning completed")
End If
If check_delete.Checked Then
' Do a clean of the destination, removing any files that don't exist in the source dir
End If
If filesscanned Then
ProgressBar1.Visible = True
ProgressBar1.Minimum = 0
ProgressBar1.Maximum = 100
ProgressBar1.Refresh()
End If
checkdir(src)
MsgBox("Copying completed")
If filesfailed > 0 Then
MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.")
End If
guistop()
End Sub
From what i can tell all calls to the System are also GUI Thread based no matter if you want them or not. And Control.CheckForIllegalCrossThreadCalls = False is very bad, you always want to write your thread and ( if beginner ) run code and everytime it breaks out to code to write a delegate and an invoke function for that part of your thread ( taking up the most minimal time ) one can in the Gui(Main) thread.
Here is an example with full sourcecode
http://www.codeproject.com/Articles/15104/Multithreading-with-VB-NET-A-beginner-s-choice
in your thread
Control.CheckForIllegalCrossThreadCalls = False -- this needs removed
If check_scanfirst.Checked Then -- this needs a delegate and invoke method
status1.Text = "Scanning..." -- this needs a delegate and invoke method
bytestocopy = 0
scandir(src) -- if scandir(has calls to gui )this needs a delegate and invoke method but inside of Scandir()
filesscanned = True
MsgBox("Scanning completed") -- this needs a delegate and invoke method ( keep in mind thread will keep running even if mesgbox not clicked )
End If
If check_delete.Checked Then -- this needs a delegate and invoke method
' Do a clean of the destination, removing any files that don't exist in the source dir
End If
If filesscanned Then
ProgressBar1.Visible = True -- this needs a delegate and invoke method
ProgressBar1.Minimum = 0 -- this needs a delegate and invoke method
ProgressBar1.Maximum = 100 -- this needs a delegate and invoke method
ProgressBar1.Refresh() -- this needs a delegate and invoke method
End If
checkdir(src)
MsgBox("Copying completed") -- this needs a delegate and invoke method
If filesfailed > 0 Then
MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.") -- this needs a delegate and invoke method
End If
guistop() -- this needs a delegate and invoke method if (guistop makes calls to gui )
so if you can't tell your making lots of calls to the gui... heres how i would write it to make it really simple
how i would write your code ( wrote this in word some code may need a tweak )
Private sub DoStuffBeforeCopy()
If check_scanfirst.Checked Then
status1.Text = "Scanning..."
bytestocopy = 0
trd_copy.ParameterizedStart(src) //start thread
end sub
CopyTask(byval src as *string*?)
scandir(src) – put the code here or make another thread ( src is better )
filesscanned = True
invoke-MsgBox("Scanning completed")
invoke If check_delete.Checked Then
If filesscanned Then
Invoke-ProgressBar1.Visible = True
Invoke-ProgressBar1.Minimum = 0
Invoke-ProgressBar1.Maximum = 100
Invoke-ProgressBar1.Refresh()
End If
checkdir(src) – put the code here or make another thread ( src is better )
invoke-MsgBox("Copying completed")
If filesfailed > 0 Then
Invoke-MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.")
End If
guistop()– put the code here or make another thread ( src is better )
End sub
** DO THIS FOR ANY Delegat / invoke needed
for threads calls with parameters
trd_copy.ParameterizedStart(src)
Delegate Sub nameofDelegate(s As Integer)
Sub nameofDelegate+NameofSub(ByVal s As Integer)
If Form1.ProgressBar1.InvokeRequired Then
Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
NameOfYourForm.Invoke(d, New Object() {s})
Else
If s = 1 Then
NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
Else
End If
End If
End Sub
For Thread calls without parametrs
trd_copy.Start()
Delegate Sub nameofDelegate()
Sub nameofDelegate+NameofSub()
If Form1.ProgressBar1.InvokeRequired Then
Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
NameOfYourForm.Invoke(d, New Object())
Else
NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
End If
End Sub