Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Question on threading

Question on threading

Scheduled Pinned Locked Moved Visual Basic
questiondata-structuresjsonhelptutorial
17 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    svanwass
    wrote on last edited by
    #1

    I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

    D L T S S 5 Replies Last reply
    0
    • S svanwass

      I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

      D Offline
      D Offline
      David Mujica
      wrote on last edited by
      #2

      So, if all of your work is being done in these worker threads, then your main application just becomes a thread manager. Right? (lets take that as true) 1) The thread manager keeps an array of status; one slot for each thread dispatched. (running/WorkDone) 2) Each thread should throw an event which represents "WorkDone"; the thread manager will listen for this event and update the corresponding array slot. 3) When all threads have been dispatched and begin their work, the thread manager just loops around and sleeps periodically checking if all status array slots have a "WorkDone" status; when that occurs you can continue with you process. Maybe extend you status array to have a start time so that you can determine if a thread is taking too long, you can take corrective action. Just a thought. :) Good luck.

      S 1 Reply Last reply
      0
      • D David Mujica

        So, if all of your work is being done in these worker threads, then your main application just becomes a thread manager. Right? (lets take that as true) 1) The thread manager keeps an array of status; one slot for each thread dispatched. (running/WorkDone) 2) Each thread should throw an event which represents "WorkDone"; the thread manager will listen for this event and update the corresponding array slot. 3) When all threads have been dispatched and begin their work, the thread manager just loops around and sleeps periodically checking if all status array slots have a "WorkDone" status; when that occurs you can continue with you process. Maybe extend you status array to have a start time so that you can determine if a thread is taking too long, you can take corrective action. Just a thought. :) Good luck.

        S Offline
        S Offline
        svanwass
        wrote on last edited by
        #3

        So, if all of your work is being done in these worker threads, then your main application just becomes a thread manager. Right? (lets take that as true)

        Yes

        1. Each thread should throw an event which represents "WorkDone"; the thread manager will
          listen for this event and update the corresponding array slot.

        How can I make the thread throw a custom event? Conversly, how do I make the thread manager listen?

        S 1 Reply Last reply
        0
        • S svanwass

          So, if all of your work is being done in these worker threads, then your main application just becomes a thread manager. Right? (lets take that as true)

          Yes

          1. Each thread should throw an event which represents "WorkDone"; the thread manager will
            listen for this event and update the corresponding array slot.

          How can I make the thread throw a custom event? Conversly, how do I make the thread manager listen?

          S Offline
          S Offline
          svanwass
          wrote on last edited by
          #4

          OK so I attempted it and I think I ran into an issue with scope. In the worker thread, I created an event

          Public Event IamDone(ByVal sender As Object, ByVal IP As String)
          

          I call that event in the RunWorkerCompleted sub

          RaiseEvent IamDone(Me, "111")

          And now I am trippng up on how to create the handler in my thread manager. I assumed it would be

          AddHandler myworkerthreadclass.IamDone, Addressof myworkerthreadclass.IamDone

          but that doenst work

          J 1 Reply Last reply
          0
          • S svanwass

            I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

            L Offline
            L Offline
            Luc Pattyn
            wrote on last edited by
            #5

            Hi, 1. Yes, you want the RunWorkerCompleted event handler to do something your main thread can notice. Lots of things are possible, here is one example: have a global variable that is initialized to the number of jobs, and gets decremented (see Interlocked.Decrement) by each RunWorkerCompleted handler, which on top of that, by checking for zero, raises a signal (see e.g. ManualResetEvent) 2. It is a bad idea to launch many BackGroundWorkers, as that would be too expensive. The better approach would be to have: - a small number of BackGroundWorkers (say two times the number of cores your system has, Environment.ProcessorCount); - a queue of jobs, filled by the main thread, and queried by those BackGroundWorkers (use a lock!); - and probably a queue of results, filled by those BackGroundWorkers (use another lock), and emptied by the main thread when it gets its "all done" signal. :)

            Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

            Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

            S 1 Reply Last reply
            0
            • L Luc Pattyn

              Hi, 1. Yes, you want the RunWorkerCompleted event handler to do something your main thread can notice. Lots of things are possible, here is one example: have a global variable that is initialized to the number of jobs, and gets decremented (see Interlocked.Decrement) by each RunWorkerCompleted handler, which on top of that, by checking for zero, raises a signal (see e.g. ManualResetEvent) 2. It is a bad idea to launch many BackGroundWorkers, as that would be too expensive. The better approach would be to have: - a small number of BackGroundWorkers (say two times the number of cores your system has, Environment.ProcessorCount); - a queue of jobs, filled by the main thread, and queried by those BackGroundWorkers (use a lock!); - and probably a queue of results, filled by those BackGroundWorkers (use another lock), and emptied by the main thread when it gets its "all done" signal. :)

              Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

              Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

              S Offline
              S Offline
              svanwass
              wrote on last edited by
              #6

              OK so I attempted it and I think I ran into an issue with scope. In the worker thread, I created an event

              Public Event IamDone(ByVal sender As Object, ByVal IP As String)

              I call that event in the RunWorkerCompleted sub

              RaiseEvent IamDone(Me, "111")

              And now I am trippng up on how to create the handler in my thread manager. I assumed it would be

              AddHandler myworkerthreadclass.IamDone, Addressof myworkerthreadclass.IamDone

              but that doesn't work

              L 1 Reply Last reply
              0
              • S svanwass

                OK so I attempted it and I think I ran into an issue with scope. In the worker thread, I created an event

                Public Event IamDone(ByVal sender As Object, ByVal IP As String)

                I call that event in the RunWorkerCompleted sub

                RaiseEvent IamDone(Me, "111")

                And now I am trippng up on how to create the handler in my thread manager. I assumed it would be

                AddHandler myworkerthreadclass.IamDone, Addressof myworkerthreadclass.IamDone

                but that doesn't work

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #7

                svanwass wrote:

                that doesn't work

                :confused:

                Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                S 1 Reply Last reply
                0
                • L Luc Pattyn

                  svanwass wrote:

                  that doesn't work

                  :confused:

                  Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                  Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                  S Offline
                  S Offline
                  svanwass
                  wrote on last edited by
                  #8

                  I wrote a simple simple version of what I'm attempting. http://www.4shared.com/file/-tIHs2FE/CustomEventsVB.html[^] Does that help explain my issue?

                  L 1 Reply Last reply
                  0
                  • S svanwass

                    I wrote a simple simple version of what I'm attempting. http://www.4shared.com/file/-tIHs2FE/CustomEventsVB.html[^] Does that help explain my issue?

                    L Offline
                    L Offline
                    Luc Pattyn
                    wrote on last edited by
                    #9

                    people here are unlikely to download anything just to maybe understand a question; what you should do is explain the symptoms ("doesn't work" tells us nothing) and tell how it differs from your expectations, then ask a specific question and/or show a relevant code snippet. :)

                    Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                    Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                    S 1 Reply Last reply
                    0
                    • L Luc Pattyn

                      people here are unlikely to download anything just to maybe understand a question; what you should do is explain the symptoms ("doesn't work" tells us nothing) and tell how it differs from your expectations, then ask a specific question and/or show a relevant code snippet. :)

                      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                      Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                      S Offline
                      S Offline
                      svanwass
                      wrote on last edited by
                      #10

                      My apologies. Main Form

                      Public Class Form1

                      Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
                          Dim passing(0, 3) As String
                          passing(0, 0) = "10.1.1.1"
                          passing(0, 1) = "10.1.1.2"
                          passing(0, 2) = "10.1.1.3"
                          passing(0, 3) = "10.1.1.4"
                          Dim myworker As New Foo(passing)
                      End Sub
                      

                      Private Sub IHeardThat() Handles Foo.IamDone
                      'this does NOT work
                      End Sub
                      End Class

                      My Foo class

                      Imports System.ComponentModel
                      Imports System.IO
                      Imports System.Threading
                      Public Class Foo

                      Public WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker
                      Public Event IamDone(ByVal sender As Object, ByVal IP As String)
                      
                      Dim devicelist(,) As String
                      Dim txtFile
                      Public Sub New(ByVal Value As String(,))
                          devicelist = Value
                          backgroundWorker1 = New BackgroundWorker
                      
                          backgroundWorker1.WorkerReportsProgress = True
                          backgroundWorker1.RunWorkerAsync(devicelist)
                      End Sub
                      Private Sub backgroundWorker1\_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles backgroundWorker1.DoWork
                      
                          ' Get the BackgroundWorker object that raised this event.
                          Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
                          Dim myargs As String(,) = e.Argument
                      
                      End Sub
                      Private Sub backgroundWorker1\_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
                      
                              RaiseEvent IamDone(Me, "Done")
                          End If
                      End Sub 
                      

                      End Class

                      So that's basically it. I attempted to write a sub that would handle the custom event but the form class doesnt see the foo class event. Does that make sense?

                      L 1 Reply Last reply
                      0
                      • S svanwass

                        My apologies. Main Form

                        Public Class Form1

                        Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
                            Dim passing(0, 3) As String
                            passing(0, 0) = "10.1.1.1"
                            passing(0, 1) = "10.1.1.2"
                            passing(0, 2) = "10.1.1.3"
                            passing(0, 3) = "10.1.1.4"
                            Dim myworker As New Foo(passing)
                        End Sub
                        

                        Private Sub IHeardThat() Handles Foo.IamDone
                        'this does NOT work
                        End Sub
                        End Class

                        My Foo class

                        Imports System.ComponentModel
                        Imports System.IO
                        Imports System.Threading
                        Public Class Foo

                        Public WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker
                        Public Event IamDone(ByVal sender As Object, ByVal IP As String)
                        
                        Dim devicelist(,) As String
                        Dim txtFile
                        Public Sub New(ByVal Value As String(,))
                            devicelist = Value
                            backgroundWorker1 = New BackgroundWorker
                        
                            backgroundWorker1.WorkerReportsProgress = True
                            backgroundWorker1.RunWorkerAsync(devicelist)
                        End Sub
                        Private Sub backgroundWorker1\_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles backgroundWorker1.DoWork
                        
                            ' Get the BackgroundWorker object that raised this event.
                            Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
                            Dim myargs As String(,) = e.Argument
                        
                        End Sub
                        Private Sub backgroundWorker1\_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
                        
                                RaiseEvent IamDone(Me, "Done")
                            End If
                        End Sub 
                        

                        End Class

                        So that's basically it. I attempted to write a sub that would handle the custom event but the form class doesnt see the foo class event. Does that make sense?

                        L Offline
                        L Offline
                        Luc Pattyn
                        wrote on last edited by
                        #11

                        does that compile at all?

                        svanwass wrote:

                        Private Sub IHeardThat() Handles Foo.IamDone

                        The IamDone event is not static/shared, how can this work?

                            Dim myworker As New Foo(passing)
                            AddHandler myworker.IamDone, AddressOf IHeardThat
                        

                        does work but is not OK as the handler is added while the BGW is alrady running, so there is a race condition. possible solutions: 1. pass the delegate to the Foo constructor, so it can add the handler on time; 2. don't start the BGW from the Foo constructor, add a method the caller should call after having set the handler. General advice: 1. consider making Foo inherit from BGW. 2. start every VB file with "option strict on" 3. tell Visual not to launch the app as long as there are compile errors 4. tell Visual to treat all warnings as errors (2+3+4 will be a PITA at first, but it will soon teach you to write correct code) :)

                        Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                        Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                        1 Reply Last reply
                        0
                        • S svanwass

                          I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

                          T Offline
                          T Offline
                          Tieske8
                          wrote on last edited by
                          #12

                          I think the best way would be using a waithandle that signals when done. If you combine the waithandles for all processes, you can use the WaitHandle.WaitAll Method. See this MSDN article for an example

                          1 Reply Last reply
                          0
                          • S svanwass

                            I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

                            S Offline
                            S Offline
                            Spectre_001
                            wrote on last edited by
                            #13

                            Save the thread class instances that you create into an array or IList. Once you have started all of your threads, you can loop through the array or list checking either the State or IsAlive property of each thread until all indicate that they are finished. This way, you don't have to block your main thread while waiting for the other threads to finish. Your main thread can continue working and just check periodically to see if all worker threads have finished.

                            Kevin Rucker, Application Programmer QSS Group, Inc. United States Coast Guard OSC Kevin.D.Rucker@uscg.mil "Programming is an art form that fights back." -- Chad Hower

                            S 1 Reply Last reply
                            0
                            • S Spectre_001

                              Save the thread class instances that you create into an array or IList. Once you have started all of your threads, you can loop through the array or list checking either the State or IsAlive property of each thread until all indicate that they are finished. This way, you don't have to block your main thread while waiting for the other threads to finish. Your main thread can continue working and just check periodically to see if all worker threads have finished.

                              Kevin Rucker, Application Programmer QSS Group, Inc. United States Coast Guard OSC Kevin.D.Rucker@uscg.mil "Programming is an art form that fights back." -- Chad Hower

                              S Offline
                              S Offline
                              svanwass
                              wrote on last edited by
                              #14

                              Seems like I have a lot to learn about the proper handeling of threads. Would any of you have a recommendation on the topic but in relations to c#? I dislike VB...

                              S 1 Reply Last reply
                              0
                              • S svanwass

                                Seems like I have a lot to learn about the proper handeling of threads. Would any of you have a recommendation on the topic but in relations to c#? I dislike VB...

                                S Offline
                                S Offline
                                Spectre_001
                                wrote on last edited by
                                #15

                                Free e-book on C# threading: www.albahari.com/threading/threading.pdf

                                Kevin Rucker, Application Programmer QSS Group, Inc. United States Coast Guard OSC Kevin.D.Rucker@uscg.mil "Programming is an art form that fights back." -- Chad Hower

                                1 Reply Last reply
                                0
                                • S svanwass

                                  OK so I attempted it and I think I ran into an issue with scope. In the worker thread, I created an event

                                  Public Event IamDone(ByVal sender As Object, ByVal IP As String)
                                  

                                  I call that event in the RunWorkerCompleted sub

                                  RaiseEvent IamDone(Me, "111")

                                  And now I am trippng up on how to create the handler in my thread manager. I assumed it would be

                                  AddHandler myworkerthreadclass.IamDone, Addressof myworkerthreadclass.IamDone

                                  but that doenst work

                                  J Offline
                                  J Offline
                                  Jason Christian
                                  wrote on last edited by
                                  #16

                                  Why don't use just use the RunWorkerCompleted event, instead of creating a new event to raise? In RunWorkerCompleted you should be able to get the key to the device, and use that to update your status collection. Or if you are on .NET 4.0 you can use one of the parallel collection to handle this much cleaner.

                                  1 Reply Last reply
                                  0
                                  • S svanwass

                                    I am attempting to write a multithreaded application. The idea is to have a scripted exe run that takes a list of devices, strips out one device and its information into an array, creates a new object of a class. which contains a backgroundworker that contains a telnet object, to telnet to said device and perform simple work (just login at this time). I have 100 device I am doing this for. So far, everything looks like it works. All 100 devices have a new class object and bgw worker created for them. My problem lies in how to determine when those have completed their work. This is a problem because the rest of the exe needs to process the results of my simple work but can only be done after all have completed. How can I tell when the work is done? I was thinking about writing something into the RunWorkerCompleted event that tallys but that seems like not the best idea. :sigh: -Steve

                                    S Offline
                                    S Offline
                                    SLDWorks
                                    wrote on last edited by
                                    #17

                                    This site has been so helpful in the past for me over 8 years. I am self taught .net, and have used it primarily with SolidWorks API since 2003. Thread for me is simply threads, and delegates. I run threads in order to crunch data. It keep the main form thread alive while crunching the info. Many times the threads have to send stuff back to the main threaded form. In order to do this without cross thread violations, we need to use delegates. My technique for sending info into a thread, and having the thread call back is rather simple. If I need to create lets say 100 threads. I will use a thread in order to do that. The thread that creates the 100 threads will sleep, only to awake and see if all threads have died. When all threads have died, the main thread cruches and then dies. The main form thread never stalls out, and gets tickled from all sides by all threads from a delegates sub. Here is the code I wrote to explain the most on these topics. Things to note are as follows: Each thread can create its node without limitations. The main thread relys on all threads being done creation. Then the assumtion is made that all thread nodes exist. This can only be true because all threads are not alive. So the main thread changes the display name of each treenode, and then dies itself. The threads and delegates take object arrays, so you can pack them full of anything, both in and out of the thread. The form is very much alive through the whole process. If only a form could speak, because this one is far from a deep sleep. Cheers, Sean P (Sldprt[ItsAboutTime])

                                    Imports System.Threading

                                    Public Class Form1

                                    Dim t1 As Thread
                                    Dim t2 As Thread()
                                    Dim c As Collection
                                    
                                    Dim treeview As TreeView
                                    
                                    Private Sub Form1\_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                                    
                                    
                                        tMain()
                                    
                                    
                                    End Sub
                                    
                                    Sub tMain()
                                    
                                        c = New Collection
                                    
                                        treeview = New TreeView
                                        Me.Controls.Add(treeview)
                                        treeview.Size = New Size(200, 400)
                                        treeview.Location = New Point(10, 6)
                                        treeview.Visible = True
                                    
                                        c.Add(100, "StartData")
                                    
                                        t1 = New Thread(AddressOf MainThreading)
                                    
                                        t1.Start(New Object() {c})
                                    
                                    End Sub
                                    
                                    Sub MainThreading(ByVal args As Object)
                                    
                                        With CType(args(0), Collection)
                                    
                                            ReDim t2(.Item("StartData"))
                                    
                                            Dim i As Integer
                                    
                                            For i = 0 To UBound(t2)
                                    
                                                .Add(i, "ThreadKey" & i)
                                    
                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups