Solved

How do you fire events from a multithreaded class?

Posted on 2009-04-01
10
205 Views
Last Modified: 2012-05-06
I currently have a class that spawns different threads.  When certain things in those threads happen, I want it to fire off an event in the thread of the original "creator" of the class.  For instance, if the Form creates the object, all events should go to the Form's thread so it can make appropriate changes.

What I'm finding is that no matter what I do in the threads, I can NOT get the events to fire in the form without causing an error that the form's controls were created in a different thread.  Really need some help here, with a very clear explanation.
0
Comment
Question by:Javin007
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
10 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24039904
What version VB.Net?....
0
 
LVL 4

Author Comment

by:Javin007
ID: 24041040
Express 2008.  
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24045318
It sounds like you are manually creating threads and not using Invoke()/Delegates to properly marshal your calls across threads.  I can show you how to do that if you like...but with VB.Net 2005 (and above) it's often easier just to use the BackgroundWorker() Control as it does this automatically for you in the ProgessChanged() and RunWorkerCompleted() events:
http://msdn.microsoft.com/en-us/library/8xs8549b.aspx
http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Author Comment

by:Javin007
ID: 24050134
I did attempt to use Invoke/Delegates, but continued to get the same error when calling the delegated method, so obviously have that set up wrong.

The BackgroundWorker seems like a better option *IF* it can "talk" back to the calling class so that class can raise events.  From what I've read here, it seems like they expect the method to just run, and eventually stop.  This loop that will be threaded should run the entire time the app is running, and occasionally fire events.  (Long story short, I'm attempting to make a sockets wrapper class.)
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24050309
You can place an Infinite loop inside the "worker" method of the BackgroundWorker control.  The thread will be automatically killed when the app is closed.

The ReportProgress() method will cause the ProgressChanged() Event to fire:
http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24050314
Do you need to see a simple example?...
0
 
LVL 4

Author Comment

by:Javin007
ID: 24050359
A small example would be awesome, thanks!
0
 
LVL 4

Author Comment

by:Javin007
ID: 24050508
Also keep in mind that this is a class, so not a form.  I'll need to create a BackgroundWorker object in code for it to be contained in the class.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 24052401
Okey dokey...here is a class that encapsulates a BackgroundWorker and raises a custom event.  Note that we do NOT have to do any manual marshalling with Invoke()/Delegates:
Public Class Form1
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim mo As New MyOperation
        AddHandler mo.SomethingHasHappened, AddressOf MyOperation_SomethingHasHappened
    End Sub
 
    Private Sub MyOperation_SomethingHasHappened(ByVal msg As String, ByVal stamp As DateTime)
        Label1.Text = msg & " | " & stamp.ToString
    End Sub
 
End Class
 
Public Class MyOperation
 
    Public Event SomethingHasHappened(ByVal msg As String, ByVal stamp As DateTime)
 
    ' obviously you can have more of these things in your class...
    Private WithEvents bgw As New System.ComponentModel.BackgroundWorker
 
    Private counter As Integer
 
    Public Sub New()
        bgw.WorkerReportsProgress = True
        bgw.WorkerSupportsCancellation = True
        bgw.RunWorkerAsync()
    End Sub
 
    Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
        ' backgroundworkers get killed automatically when the app shuts down...
        While True
            ' you can acess anything inside MyOperation from here to make decisions etc...
            System.Threading.Thread.Sleep(1000)
            counter = counter + 1
            bgw.ReportProgress(counter) ' this just makes ProgressChanged() fire below
        End While
    End Sub
 
    Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
        ' this is already marshaled to the UI thread because the MyOperation class was created on the UI thread
        ' make the main UI receive the event
        ' again, you can acess stuff inside MyOperation if need be, or pass things via "e.UserState" from the "worker"
        RaiseEvent SomethingHasHappened("Greeting #" & e.ProgressPercentage, DateTime.Now)
    End Sub
 
    Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
        ' you can raise a different event here...
    End Sub
 
End Class

Open in new window

0
 
LVL 4

Author Closing Comment

by:Javin007
ID: 31565228
Perfect!  This is exactly what I needed.  Delegates/Invoke was entirely too complex.
0

Featured Post

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction While answering a recent question (http://www.experts-exchange.com/Q_27402310.html) in the VB classic zone, I wrote some VB code in the (Office) VBA environment, rather than fire up my older PC.  I didn't post completely correct code o…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

740 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