Solved

vb.net threading

Posted on 2011-09-13
9
363 Views
Last Modified: 2012-05-12
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?


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

Open in new window

0
Comment
Question by:AidenA
9 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 36529391
Also, I'm getting cross thread errors with SelectSheet which is another form.
This is because you are trying to update the GUI from a thread other than the one the GUI was created on--typically, the main thread. You have to invoke a delegate in order to update your GUI from a different thread.

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.
0
 
LVL 18

Expert Comment

by:Dennis Aries
ID: 36529413
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.

0
 

Author Comment

by:AidenA
ID: 36529818
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?
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)

Open in new window

0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 36529921
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.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:AidenA
ID: 36530817
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("myexceldoc.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
0
 

Author Comment

by:AidenA
ID: 36530909
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.lblStatusLabel, "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(ByVal 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?

0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 250 total points
ID: 36530935
Change:

   Me.Invoke(...)

To:

   Me.BeginInvoke(...)

Invoke() is synchronous so it can cause deadlock issues when Join() becomes involved....
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 250 total points
ID: 36530965
Is there a way of seeing exactly where the thread t3 is?
I think Idle_Mind's got you covered for your error, but to answer this question: you do have the Threads debug window (Debug->Threads). You should be able to set a breakpoint in your threaded function as well. It will hit for each thread, but in combination with the Threads window you should be able to tell which thread you are currently inspecting.
0
 

Author Closing Comment

by:AidenA
ID: 36535331
yep that did it. thanks for the info!

Aiden
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now