AidenA
asked on
vb.net threading
Hi, I am new to threading and wanted to see how I could implement into one of my windows apps. So I do something like that shown below (running the same sub mySub from different threads).
But, as soon as I start to do that, I realise that I've no idea what that it's actually going to do exactly and I'm sort of thinking 'how could that possibly work'. I'm thinking these threads are going to intefere with eachother and perhaps I should be starting three instances of the class with sub mySub instead of having three threads working on the same sub in the same class? I'm assuming all the variables would keep getting reset by the different threads so passing the parameters becomes pointless (i.e. you pass the parameter blnRateAll which is set to True for thread one, but then thread 2 starts up and sets it False for instance, and now thread 1 see's it at False instead of True?).
So, how exactly would you want to set something like this up? Three threads running the same subroutine? Also, I'm getting cross thread errors with SelectSheet which is another form. For instance, it can't set lstSelectSheet itself because of the cross thread error. I had previously found some code creating a delegate sub to invoke the label on that form no matter what thread called it which seemed to work ok, so I guess I would have to do something similar again?
But, as soon as I start to do that, I realise that I've no idea what that it's actually going to do exactly and I'm sort of thinking 'how could that possibly work'. I'm thinking these threads are going to intefere with eachother and perhaps I should be starting three instances of the class with sub mySub instead of having three threads working on the same sub in the same class? I'm assuming all the variables would keep getting reset by the different threads so passing the parameters becomes pointless (i.e. you pass the parameter blnRateAll which is set to True for thread one, but then thread 2 starts up and sets it False for instance, and now thread 1 see's it at False instead of True?).
So, how exactly would you want to set something like this up? Three threads running the same subroutine? Also, I'm getting cross thread errors with SelectSheet which is another form. For instance, it can't set lstSelectSheet itself because of the cross thread error. I had previously found some code creating a delegate sub to invoke the label on that form no matter what thread called it which seemed to work ok, so I guess I would have to do something similar again?
Sub ThreadStart()
Dim alParam As New ArrayList
Dim paramTS As New ParameterizedThreadStart(AddressOf mySub)
Dim t1 As Thread = Nothing
Dim t2 As Thread = Nothing
Dim t3 As Thread = Nothing
'Create parameter array for the thread
Dim d1 As New SelectSheet
d1.lblSelectSheet.Text = "Please put in file 1 name"
d1.ShowDialog()
alParam.Add(d1.lstSelectSheet.SelectedItem.ToString())
alParam.Add(True) 'for blnRateAll
alParam.Add(True) 'for blnFirstPass
alParam.Add(False) 'for blnSecondPass
alParam.Add(False) 'for blnFinalPass
d1.Dispose()
t1 = New Thread(paramTS)
t1.Start(alParam)
Dim d2 As New SelectSheet
d2.lblSelectSheet.Text = "Please put in file 2 name"
d2.ShowDialog()
alParam(0) = d2.lstSelectSheet.SelectedItem.ToString()
alParam(2) = False : alParam(3) = True
t2 = New Thread(paramTS)
t2.Start(alParam)
Dim d3 As New SelectSheet
d1.lblSelectSheet.Text = "Please put in file 3 name"
d3.ShowDialog()
alParam(0) = d3.lstSelectSheet.SelectedItem.ToString()
alParam(3) = False : alParam(4) = True
t3 = New Thread(paramTS)
t1.Start(alParam)
End Sub
Multithreading is a large subject, not something that can be explained in a mere answer. I would suggest reading Microsoft MSDN on the subject to get in-depth information.
ASKER
yeah, have been reading a bit more there and this is where i am so far (see below).
So, i think i sort of got it working. Had to put synclock onto mySub to avoid the issues you mention, and then put the code below into my main function (and changed some things around to avoid th GUI issue... but I can solve that part I think)
That seemed to more or less solve the issue but I noticed that thread t3 was for some reason running before t2 which was causing a problem. That was ok, I can remove the reason why they must run in order. But, as a consequence, I need the application to wait at a particular point for threads t1, t2, and t3, to terminate before running the final part of the code (which is a cleanup routine).
So, reading a bit, seems like I need thread.join to do this and you can see that in my code below. However, when i ran it, t1.join or t2.join or t3.join never actually completes. It waits for an indeterminate amount of time. So, reading a bit further I think the reason for this is the thread is not terminating. MySub has an end... so I don't know why this would be?
Any ideas why thread.join is not completing?
So, i think i sort of got it working. Had to put synclock onto mySub to avoid the issues you mention, and then put the code below into my main function (and changed some things around to avoid th GUI issue... but I can solve that part I think)
That seemed to more or less solve the issue but I noticed that thread t3 was for some reason running before t2 which was causing a problem. That was ok, I can remove the reason why they must run in order. But, as a consequence, I need the application to wait at a particular point for threads t1, t2, and t3, to terminate before running the final part of the code (which is a cleanup routine).
So, reading a bit, seems like I need thread.join to do this and you can see that in my code below. However, when i ran it, t1.join or t2.join or t3.join never actually completes. It waits for an indeterminate amount of time. So, reading a bit further I think the reason for this is the thread is not terminating. MySub has an end... so I don't know why this would be?
Any ideas why thread.join is not completing?
Dim alParam As New ArrayList
Dim paramTS As New ParameterizedThreadStart(AddressOf mySub)
Dim t1 As Thread = Nothing
Dim t2 As Thread = Nothing
Dim t3 As Thread = Nothing
'Create parameter array for the thread
Dim d1 As New SelectSheet(glWorksheets)
d1.lblSelectDHLSheet.Text = "Please select the r189 for customer 41335."
d1.ShowDialog()
alParam.Add(d1.lstSelectSheet.SelectedItem.ToString())
alParam.Add(True) 'for blnRateAll
alParam.Add(True) 'for blnFirstPass
alParam.Add(False) 'for blnSecondPass
alParam.Add(False) 'for blnFinalPass
d1.Dispose()
t1 = New Thread(paramTS)
t1.Start(alParam)
Dim d2 As New SelectSheet(glWorksheets)
d2.lblSelectDHLSheet.Text = "Please select the r189 for customer 25933."
d2.ShowDialog()
alParam(0) = d2.lstSelectSheet.SelectedItem.ToString()
alParam(2) = False 'for blnFirstPass
alParam(3) = True 'for blnSecondPass
t2 = New Thread(paramTS)
t2.Start(alParam)
Dim d3 As New SelectSheet(glWorksheets)
d3.lblSelectDHLSheet.Text = "Please select the r189 for customer 10929."
d3.ShowDialog()
alParam(0) = d3.lstSelectSheet.SelectedItem.ToString()
alParam(3) = False 'for blnSecondPass
alParam(4) = True 'for blnFinalPass
t3 = New Thread(paramTS)
t3.Start(alParam)
'make threads wait before we cleanup the references
Dim blnT1 As Boolean = t1.Join(50000)
Dim blnT2 As Boolean = t2.Join(50000)
Dim blnT3 As Boolean = t3.Join(50000)
Any ideas why thread.join is not completing?Without seeing the complete code, that is going to be difficult to diagnose.
You might find it easier to work with the ThreadPool than to manage the creation of threads yourself.
ASKER
yeah, but need to learn how to use threads... once I have a decent understanding I'll probably just simplify it and use threadpool or just a background worker thread for the UI or however you're supposed to do it.
But I just want to figure out why thread.join isn't working first. It actually works ok if I make mySub a simple subroutine which doens't really do anything. All threads join correctly. So the problem is in mySub which is a subroutine which automates excel... so it is working on excel objects. I noticed that t1 and t2 joined ok if I moved the opening of an excel file into the main thread (i.e. the code wb = xlApp.Workbooks.Open("myex celdoc.xls ") is moved out of mySub and called before creating the threads).
So again, not sure what was causing that error, but that solved it... I think. But not sure why t3 which is also calling mySub and is performing more or less the same actions as far as I can tell, is not joining.
I mean, how do I even go about trying to see where the error is? Is there a way of seeing exactly where the thread t3 is? What I can see right now is that it doesn't join... but I don't know where exactly it currently is? How do I debug this issue?
Thanks
But I just want to figure out why thread.join isn't working first. It actually works ok if I make mySub a simple subroutine which doens't really do anything. All threads join correctly. So the problem is in mySub which is a subroutine which automates excel... so it is working on excel objects. I noticed that t1 and t2 joined ok if I moved the opening of an excel file into the main thread (i.e. the code wb = xlApp.Workbooks.Open("myex
So again, not sure what was causing that error, but that solved it... I think. But not sure why t3 which is also calling mySub and is performing more or less the same actions as far as I can tell, is not joining.
I mean, how do I even go about trying to see where the error is? Is there a way of seeing exactly where the thread t3 is? What I can see right now is that it doesn't join... but I don't know where exactly it currently is? How do I debug this issue?
Thanks
ASKER
well surprisingly I tracked down the error actually... was able to just wait until t1 and t2 would have definitely finished and then debug so I could be sure I was on t3...
Error is coming from
SetProgress_ThreadSafe(Me. lblStatusL abel, "Closing Files", ProgressBar1, ProgressBar1.Value + 1)
which is the code I was using to avoid the GUI error in the beginning. There is the delegate at the beginning;
Delegate Sub SetProgress(ByVal lbl As Label, ByVal txt As String, ByVal pgb As ProgressBar, ByVal intProgress As Integer)
and the sub itself
Private Sub SetProgress_ThreadSafe(ByV al lbl As Label, ByVal txt As String, ByVal pgb As ProgressBar, ByVal intProgress As Integer)
' InvokeRequired required compares the thread ID of the calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If lbl.InvokeRequired Then
Dim MyDelegate As New SetProgress(AddressOf SetProgress_ThreadSafe)
Me.Invoke(MyDelegate, New Object() {lbl, txt, pgb, intProgress})
Else
lbl.Text = txt
pgb.Value = intProgress
End If
... and on t3 it seemed to fail on the line Me.Invoke(MyDelegate, New Object() {lbl, txt, pgb, intProgress})
So, that code works fine with t1 and t2... does that info help you identify what the error could be?
Error is coming from
SetProgress_ThreadSafe(Me.
which is the code I was using to avoid the GUI error in the beginning. There is the delegate at the beginning;
Delegate Sub SetProgress(ByVal lbl As Label, ByVal txt As String, ByVal pgb As ProgressBar, ByVal intProgress As Integer)
and the sub itself
Private Sub SetProgress_ThreadSafe(ByV
' InvokeRequired required compares the thread ID of the calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If lbl.InvokeRequired Then
Dim MyDelegate As New SetProgress(AddressOf SetProgress_ThreadSafe)
Me.Invoke(MyDelegate, New Object() {lbl, txt, pgb, intProgress})
Else
lbl.Text = txt
pgb.Value = intProgress
End If
... and on t3 it seemed to fail on the line Me.Invoke(MyDelegate, New Object() {lbl, txt, pgb, intProgress})
So, that code works fine with t1 and t2... does that info help you identify what the error could be?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
yep that did it. thanks for the info!
Aiden
Aiden
The big thing with threading is the management of shared resources and/or objects. Any time you have something being shared between threads, there is the potential to encounter deadlocks and race conditions. These scenarios are what you need to account for in your code. Most often, the way you handle this is through some sort of locking mechanism. This locking mechanism is what protects your critical section, the part of code that must only allow one thread to be executing at any given time, from multiple threads accessing the shared resources/objects.