What to do? lock()? invoke()? begininvoke()?

D

David Logan

I have an application using sockets, and it uses the asynchronous method
for receiving (and others, but receiving is the basic problem.)

In short, I want:

class someClass: Form
{
mySocketClass sss;

...

sss.ReceivedData += myHandler

...

myHandler(String data) {
do cool stuff
}
}

The question is, in "mySocketClass", what is the best way to send an
event to the main class? Currently I am using the default event handling
stuff, but I am pretty certain that "myHandler" is being called
asynchronously without any thread protection (i.e. locking)

I don't really care if the socket implentation sends events
synchronously or asynchronously, so long as when "someClass" gets the
event, it is synchronous with respect to itself, it's own thread, and
whatever else may be going on there (it's a form, so mouse clicks for
example.)

I have not really found anything yet that gives me a good explanation of
Invoke(), Begin/End/Invoke(), lock(), etc.

What is the best way to send events from a worker thread to the main
thread? Or what is the best way for a class in a worker class to call
the main class/main thread event handlers?

David Logan
 
N

Nicholas Paldino [.NET/C# MVP]

David,

Personally, I think in this scenario, it is best to have the event
listener determine what is the best course of action, and do the proper
thing when an event is fired. I think that the responsiblity of the
component raising the event is to be clear about just what it does and how
it does it.

In other words, I think that you should say that your socket can fire
events on any thread. Then, the listeners would be responsible for
performing the event handling in a way that fits the application that they
are writing. I believe that to have your class be responsible for
marshaling the event to another thread requires too much specific knowledge
of the event handler (which flys in the face of events in the first place,
as they are an attempt to loosely couple components together).

That being said, I think that when the event is fired and your listener
gets the notification, it should make the determination as to how to send
the processing to another thread. If the component was created on a windows
UI thread (which has a message loop), then Invoke/BeginInvoke/EndInvoke is
the way to go. If it is not, then you will have to have some other
mechanism to get the notification to that thread.

Hope this helps.
 
D

David Logan

Nicholas said:
David,

Personally, I think in this scenario, it is best to have the event
listener determine what is the best course of action, and do the proper
thing when an event is fired. I think that the responsiblity of the
component raising the event is to be clear about just what it does and how
it does it.

OK. I have no problem with this. I would agree about removing knowledge
and responsibility from classes using the worker class.
In other words, I think that you should say that your socket can fire
events on any thread. Then, the listeners would be responsible for
performing the event handling in a way that fits the application that they
are writing. I believe that to have your class be responsible for
marshaling the event to another thread requires too much specific knowledge
of the event handler (which flys in the face of events in the first place,
as they are an attempt to loosely couple components together).

That being said, I think that when the event is fired and your listener
gets the notification, it should make the determination as to how to send
the processing to another thread. If the component was created on a windows
UI thread (which has a message loop), then Invoke/BeginInvoke/EndInvoke is
the way to go. If it is not, then you will have to have some other
mechanism to get the notification to that thread.

Hope this helps.

Again, fine, but the questions then become:

1) How to determine if it's a synchronous request, asynchronous request,
same thread or different thread?

2) What methods do I use to complete the transaction?

....

#2 is not exactly my question. I see the direct delegate call, and I am
aware of Invoke() BeginInvoke() and EndInvoke(), but I am unclear as to
how they are used.

Would I do something like callingClass.Invoke(new EventHandler) ?

Do I need to call into the calling class so that it can make a call to
this.Invoke ?

I have seen many examples on the net, but so far, I have been unable to
just get a technical explanation of threads, events, and the calls to
manage them. Therefore, the examples are not yet making sense to me.

David Logan
 
A

AlexS

Hi, David

For technical explanation of threading I would suggest to get the book, like
Programming Windows Applications of Jeffrey Richter or similar one. However
in your case, you might want to experiment how control is passed between
your threads, it usually makes things very clear.

Use Console.WriteLine or Debug.WriteLine (or Trace class) in your listener
to log control logic when invoking events and related threads information.
When you do async calls, pass related information (thread call, async call)
in event arguments. And keep in mind, that Invoke or BeginInvoke are
required, when you need to get back to UI or initiating control thread. If
you see that your event handler executes on thread, which is different from
one were event was originated, you might need to use locking to prevent
synchronization and Invoke.
Test always on multiprocessor machine. Single processor ones usually have
much less problems with locks, racing and synchronization.
When you complete transaction, once again check on which thread you are and
act accordingly. Usually transaction completion means some user feedback, so
BeginInvoke.
This one could be useful
http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/ - there are
some simple samples, which you can try.

HTH
Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top