theads and events

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I want to create a non-UI class that has a long running worker thread in it.
The worker thread periodically raises progress events or a done event that is
sent to the Main/UI thread.

Is there a way to raise events from the class that will be run on the
Main/UI thread?
I don't want to use callbacks to the UI thread, just a class that raises
events.
The problem I am having is how to get at the ISychronizeInvoke interface
from a class.

The only kludge around I could come up with is to pass in delegates to the
constructor and then Invoke them. Not very user friendly because they have
to have the correct signatures.
 
You need to get hold of a reference to ISynchronizeInvoke that lives on the thread you want to pass notifications to - you could have more than one UI thread. You could wrap this functionality in a class that has a static instance (which holds an ISynchronizeInvoke) and then have a method on that class which takes a Delegate and an object[]. Then all you need to do is check in that method whether InvokeRequired = true and if it is call ISynchonrize.BeginInvoke, otherwise just call Delegate.Method.Invoke();

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

I want to create a non-UI class that has a long running worker thread in it.
The worker thread periodically raises progress events or a done event that is
sent to the Main/UI thread.

Is there a way to raise events from the class that will be run on the
Main/UI thread?
I don't want to use callbacks to the UI thread, just a class that raises
events.
The problem I am having is how to get at the ISychronizeInvoke interface
from a class.

The only kludge around I could come up with is to pass in delegates to the
constructor and then Invoke them. Not very user friendly because they have
to have the correct signatures.
 
Chuck P said:
I want to create a non-UI class that has a long running worker thread in it.
The worker thread periodically raises progress events or a done event that is
sent to the Main/UI thread.

Is there a way to raise events from the class that will be run on the
Main/UI thread?
I don't want to use callbacks to the UI thread, just a class that raises
events.

You've basically got to use Invoke/BeginInvoke somewhere.
The problem I am having is how to get at the ISychronizeInvoke interface
from a class.

The only kludge around I could come up with is to pass in delegates to the
constructor and then Invoke them. Not very user friendly because they have
to have the correct signatures.

You can call Invoke or BeginInvoke on the delegate in the method that
raises the event - so the event would look just like a normal event to
the outside world, but would end up getting executed on the UI thread.
 
As a work around,
in the constructor of the class I put the calling form and then have a
module level Sync object. The class then throws and event via a delegate.
Much much cleaner than putting the delegates in the calling form.

I was wondering if there was a better way to find out the thread that
instantiated the class.

Sub New(ByVal TargetForm As Form, ByVal ds As DataSet, Optional ByVal
StatusBarIncrements As Integer = 100)

m_sync = CType(TargetForm, System.ComponentModel.ISynchronizeInvoke)
End Sub

Private Sub ReportPercentComplete(ByVal percent As Integer)
Static arg() As Object = {0}
arg(0) = percent

Static del As PercentCompleteDelegate
del = New PercentCompleteDelegate(AddressOf RaisePercentComplete)
sync.Invoke(del, arg) 'invoke is always required, don't bother to
check

End Sub

Private Sub RaisePercentComplete(ByVal percent As Integer)
RaiseEvent PercentComplete(percent)
End Sub
 
Hi

To call the function which will relative Main UI thread object, we do need
to marshal the call back onto the main UI Thread.
Since Event is kind of callback mechanism, we can consider it as a function
point. So to run the function point on the Main UI thread, we need to do
marshal.
In winform, we can use the Control.Invoke function to do the job.
Here the control can be any control on the form, include the form which is
derived from control.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
I follow that,

I was just trying to figure what was the best way to identify the thread
where the events from the class will be processed. The long running threaded
process is in a stand alone class that will throw events to a Form.
Currently, I pass a reference to the form in the class constructor, which
seems kind of kludgey. Do you know a better way? Let the class inherit from
control, some API call, something else?
 
Hi

So far we do use the method to handle the multitheading in winforms.
For a more elegant approach, you may try to take a look at the links below.
Practical Multithreading for Client Apps
http://msdn.microsoft.com/msdnmag/issues/04/01/NET/default.aspx

Safe, Simple Multithreading in Windows Forms, Part 1
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms06112002.asp

Safe, Simple Multithreading in Windows Forms, Part 2
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms08162002.asp

Safe, Simple Multithreading in Windows Forms, Part 3
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms01232003.asp

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hello,

I reviewed the whole thread. The general way to call methods on the
progress bar control is by calling the Form.Invoke() method, which takes a
delegate to a method which would perform this operation. Form.Invoke()
performs the invocations using the Form's thread, which is the "good" way
to perform these operations. This means that every time you want to update
your UI from another thread, you'd need to create 2 separate methods and 2
separate delegates. One method and delegate to recieve the event from the
thread which then "Invoke"s another delegate to a method on the form, whcih
actually updates the UI.

Please refer to http://weblogs.asp.net/rosherove/articles/7171.aspx.
MVP Roy Osherove has a good article on it and he has developed two classes,
UIThreadManager and UIThreadHandler to simply the work.

ISynchronizeInvoke can also be used on it. Community member Gregory has
done it before. Please refer to the following link for details:
http://groups.google.com/groups?hl=en&lr=&selm=005d01c3cefb$95a7a150$a40
1280a%40phx.gbl

Does that answer your question?

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
Register to Access MSDN Managed Newsgroups!
-http://support.microsoft.com/default.aspx?scid=/servicedesks/msdn/nospam.as
p&SD=msdn

This posting is provided "AS IS" with no warranties, and confers no rights.
 
For any interested.
I took my long running class and had it inherit from a control
When the class intializes do
.ControlCreate
Now you have a handle and you know what thread created the control.
So now you can
me.invoke(delegate,arg)

Where the delegate points to a procedure which raises an event.
 
Hi,

Thanks very much for sharing it in the community. If you have any questions
on it, please feel free to post here and we will follow up.

Have a good day.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
Register to Access MSDN Managed Newsgroups!
-http://support.microsoft.com/default.aspx?scid=/servicedesks/msdn/nospam.as
p&SD=msdn

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Back
Top