Question on threading
-
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.
-
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?
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.
-
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.
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 ClassMy Foo class
Imports System.ComponentModel
Imports System.IO
Imports System.Threading
Public Class FooPublic 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?
-
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 ClassMy Foo class
Imports System.ComponentModel
Imports System.IO
Imports System.Threading
Public Class FooPublic 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?
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.
-
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
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
-
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
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
-
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
-
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...
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
-
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
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.
-
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
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)