Raising UI-level events from a thread without using Invoke?

T

Thomas Due

Hi,

I have a class which monitors a TCP socket. This will on occasion raise an event which can be handled by a GUI.

Now, I am aware of the

if(InvokeRequire) {
EventHandler d = new EventHandler();
Invoke(d, new object[]{sender, e});
} else {
...
}

structure, but I was wondering if there is a way to avoid it?

The way I raise the events is like this:

// declaration in thread class
public event EventHandler<CustomEventArgs> EventHappening;

// Usage in thread class
if (somethingorotherhappening)
if (EventHappening != null)
EventHappening(this, new CustomEventArgs());


Thank you in advance.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"Digressions, objections, delight in mockery, carefree mistrust are
signs of health; everything unconditional belongs in pathology."
-- Friedrich Nietzsche
 
B

Brian Gideon

Hi,

You could have the worker class class enqueue the event messages into
a queue (synchronized appropriately of course) while the UI thread
polls on some interval to dequeue and process them.

Brian
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

I have a class which monitors a TCP socket. This will on occasion raise an
event which can be handled by a GUI.

Now, I am aware of the

if(InvokeRequire) {
EventHandler d = new EventHandler();
Invoke(d, new object[]{sender, e});
} else {
...
}

structure, but I was wondering if there is a way to avoid it?


Why you want to avoid it?
It's the easier way of doing it.
 
P

Peter Duniho

On Tue, 13 Feb 2007 07:20:28 -0800, Ignacio Machin ( .NET/ C# MVP )
<machin TA
Why you want to avoid it?
It's the easier way of doing it.

Well, one reason may be that he doesn't want the signaling thread to have
to block, waiting on the UI thread.

Of course, one solution to that would be to use BeginInvoke instead of
Invoke. Same general idea, but without the blocking behavior. And just
as easy.

Pete
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Peter Duniho said:
On Tue, 13 Feb 2007 07:20:28 -0800, Ignacio Machin ( .NET/ C# MVP )
<machin TA

Well, one reason may be that he doesn't want the signaling thread to have
to block, waiting on the UI thread.

Of course, one solution to that would be to use BeginInvoke instead of
Invoke. Same general idea, but without the blocking behavior. And just
as easy.

Yes, you are correct, that would be only reason why not using Invoke.
 
T

Thomas Due

Ignacio said:
Why you want to avoid it?
It's the easier way of doing it.

I know, but it is butt-ugly and I have to do it each and every time I handle an event from the tcp-handler class.

It would be much cleaner (in my opinion) if I could pack all that invoking away in my code away from the GUI.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"If you know the enemy and know yourself, you need not fear the result
of a hundred battles. If you know yourself but not the enemy, for every
victory gained you will also suffer a defeat. If you know neither the
enemy nor yourself, you will succumb in every battle."
-- Sun-Tzu
 
T

Thomas Due

Peter said:
Well, one reason may be that he doesn't want the signaling thread to have to block, waiting on the UI thread.

There's that :) Also, I think the InvokeRequired structure is ugly and I have to do everytime I handle an event from the signaling thread. If I could put the synchronization into the signaling thread that would be sweet.
Of course, one solution to that would be to use BeginInvoke instead of Invoke. Same general idea, but without the blocking behavior. And just as easy.


Sounds interesting, I'll look into BeginInvoke/EndInvoke.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"My choice early in life was either to be a piano-player in a
whorehouse or a politician. And to tell the truth, there's hardly
any difference."
-- Harry S. Truman
 
T

Thomas Due

Brian said:
You could have the worker class class enqueue the event messages into
a queue (synchronized appropriately of course) while the UI thread
polls on some interval to dequeue and process them.

Yeah, something like that, but how would I handle it? Could I do with something WaitCallback?

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"It is hard enough to remember my opinions, without also remembering my
reasons for them!"
-- Friedrich Nietzsche
 
B

Brian Gideon

I know, but it is butt-ugly and I have to do it each and every time I handle an event from the tcp-handler class.

It would be much cleaner (in my opinion) if I could pack all that invoking away in my code away from the GUI.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"If you know the enemy and know yourself, you need not fear the result
of a hundred battles. If you know yourself but not the enemy, for every
victory gained you will also suffer a defeat. If you know neither the
enemy nor yourself, you will succumb in every battle."
-- Sun-Tzu

Hi,

Take a look at the pattern Microsoft used for the
System.Timers.Timer. There is a SynchronizingObject property that
accepts an ISynchronizeInvoke object used for marshaling. The
marshaling happens inside the Timer class and so is encapsulated away
from the GUI. The Invoke and BeginInvoke methods on Forms and
Controls come from the ISynchronizeInvoke interface.

Brian
 
A

Adam Clauss

Thomas Due said:
It would be much cleaner (in my opinion) if I could pack all that invoking
away in my code away from the GUI.

Why should the 'non-GUI' portion of your application need to be aware of GUI
synchronization? It should be the GUI's responsibility to do that - not
your socket code.
 
T

Thomas Due

Adam said:
Why should the 'non-GUI' portion of your application need to be aware of GUI synchronization? It should be the GUI's responsibility to do that - not your socket code.

Bascially because I don't want to have to bother with it in the GUI code.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"To fight and conquer in all your battles is not supreme excellence;
supreme excellence consists in breaking the enemy's resistance without
fighting."
-- Sun-Tzu
 
T

Thomas Due

Brian said:
Hi,

Take a look at the pattern Microsoft used for the
System.Timers.Timer. There is a SynchronizingObject property that
accepts an ISynchronizeInvoke object used for marshaling. The
marshaling happens inside the Timer class and so is encapsulated away
from the GUI. The Invoke and BeginInvoke methods on Forms and
Controls come from the ISynchronizeInvoke interface.

Brian

Cool. I'll take a look at it. I am thinking about examining BackgroundWorker as well.

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"If you know the enemy and know yourself, you need not fear the result
of a hundred battles. If you know yourself but not the enemy, for every
victory gained you will also suffer a defeat. If you know neither the
enemy nor yourself, you will succumb in every battle."
-- Sun-Tzu
 
B

Brian Gideon

Why should the 'non-GUI' portion of your application need to be aware of GUI
synchronization? It should be the GUI's responsibility to do that - not
your socket code.

Hi,

In the case of System.Timers.Timer it isn't really aware of the GUI.
The ISynchronizeInvoke interface decouples the two. The pattern
definitely cleans up the code on the observer side so I think it is
beneficial.

Brian
 
B

Brian Gideon

Yeah, something like that, but how would I handle it? Could I do with something WaitCallback?

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"It is hard enough to remember my opinions, without also remembering my
reasons for them!"
-- Friedrich Nietzsche

Hi,

Well, what I was talking about was using the producer-consumer
pattern. That's one way of achieving complete independence of the
ISynchronizeInvoke methods. Take a look at the following article
which has an example of how to do this.

http://www.yoda.arachsys.com/csharp/threads/deadlocks.shtml

However, this all moot now since I better understand what it is you're
looking for.

Brian
 
P

Peter Duniho

On Wed, 14 Feb 2007 02:58:12 +0800, Ignacio Machin ( .NET/ C# MVP )
<machin TA
Yes, you are correct, that would be only reason why not using Invoke.

Well, I don't think it's safe to say it's the *only* reason. Just because
you (or I) cannot think of another reason at the moment, that's no reason
to believe that there aren't other reasons to not use Invoke or
BeginInvoke.

But it does seem in this case, BeginInvoke might be what the OP is looking
for. :)

Pete
 
M

Marc Gravell

On a pattern level (a bit OT from the OP); it is nice to unburden the
observer, but I have a problem with this: it assumes you only have UI
observer(s) on the same thread as is making the changes to the object
model. Indeed, the standard winform bindings make this assumption,
with the sad effect that the UI fails to update correctly to changes
made by different threads.

You can fix this by rolling your own binding subclass, but it would be
nice if this tweak could be inserted directly into the Binding (etc)
class - on the premise (in agreement with Adam) that it is their job
to co-ordinate object (non-UI) changes to the UI; why should
"observer" fail just because you have multiple threads?

OK, you could detach the observer(s) while making the changes, but
that assumes that your UI is anticipating the change... which broadly
is the opposite of "observer". It also completely breaks the
(occasionally useful) idea of havbing multiple UI threads watching the
same data... you'd need to tell all the other UI threads to detach and
then re-attach... pointless.

</rant> ;-p

Marc
 
T

Thomas Due

I just stumbled upon this approach, which *seems* to work nicely, but would any of you gurus please comment on it? It is not *exactly* what I was looking for, but it still simplifies the code greatly.

http://www.csharper.net/blog/methodinvoker___anonymous_methods___teh_r0x0r.aspx

Basically this method allows me to switch this:


private void someEventHandler(object sender, EventArgs e)
{

if(this.InvokeRequired)
{
EventHandler d = new EventHandler(someEventHandler);
this.Invoke(d, new object[]{sender, e});

}
else
{
// do some actual work.
}
}

with this:

private void someEventHandler(object sender, EventArts e)
{
this.Invoke((MethodInvoker)delegate
{
// do some actual work.
});
}

Does this have some unseen dangers that I don't know of?

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"War is based on deception."
-- Sun-Tzu
 
B

Brian Gideon

I just stumbled upon this approach, which *seems* to work nicely, but would any of you gurus please comment on it? It is not *exactly* what I was looking for, but it still simplifies the code greatly.

http://www.csharper.net/blog/methodinvoker___anonymous_methods___teh_...

Basically this method allows me to switch this:

private void someEventHandler(object sender, EventArgs e)
{

if(this.InvokeRequired)
{
EventHandler d = new EventHandler(someEventHandler);
this.Invoke(d, new object[]{sender, e});

}
else
{
// do some actual work.
}

}

with this:

private void someEventHandler(object sender, EventArts e)
{
this.Invoke((MethodInvoker)delegate
{
// do some actual work.
});

}

Does this have some unseen dangers that I don't know of?

--
Thomas Due
Posted with XanaNews version 1.18.1.6

"War is based on deception."
-- Sun-Tzu

Thomas,

Yeah, that's fine. It's using an anonymous method which makes the
syntax cleaner. Of course, the obvious functional difference is that
it isn't checking InvokeRequired first, but I suspect Invoke just
executes the delegate synchronously if it's called from the UI thread
anyway.

Brian
 
J

Jon Skeet [C# MVP]

Thomas Due said:
I just stumbled upon this approach, which *seems* to work nicely, but
would any of you gurus please comment on it? It is not *exactly* what
I was looking for, but it still simplifies the code greatly.

http://www.csharper.net/blog/methodinvoker___anonymous_methods___teh_r0x0r.aspx

Basically this method allows me to switch this:

Does this have some unseen dangers that I don't know of?

Well, anonymous methods can capture local variables in unexpected ways,
but other than that, I shouldn't think it's too bad.

See http://pobox.com/~skeet/csharp/csharp2/delegates.html for more on
that front.

Note, however, that the two methods you've given do different things -
the first only calls Invoke when it needs to, the second *always* calls
Invoke, even if it's already on the right thread.
 
P

Peter Duniho

Yeah, that's fine. It's using an anonymous method which makes the
syntax cleaner. Of course, the obvious functional difference is that
it isn't checking InvokeRequired first, but I suspect Invoke just
executes the delegate synchronously if it's called from the UI thread
anyway.

I would hope it does. Otherwise, wouldn't the call to Invoke simply
deadlock? That is, on another thread it would wait for the main thread to
process the Invoke, but if the main thread is waiting already (because
it's the thread calling Invoke) it seems to me it would never get a chance
to process the Invoke.

I've always found it a bit odd that all the "classic" Invoke examples
bother to check that Invoke is required. Seems to me that the performance
penalty for always calling Invoke should be minimal, assuming there is one
at all. And of course, checking whether Invoke is required must have its
own peformance penalty too, and writing the code that way forces callers
not on the main thread to always incur that penalty.

Basically, it's not at all clear to me why one would typically gain any
benefit from checking whether Invoke is required. If it *might* be
required, then just use it. Should work fine that way, IMHO and the
average performance should be *better* that way.

Pete
 

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