BeginInvoke and callbacks

G

Guest

Hello,

If I understand BeginInvoke correctly, when it is called your delegate is
run on a thread pool thread. Now, if you supplied a callback delegate, that
too is called on the same thread pool thread.

My question is this: Do I ever need to check the value of InvokeRequired in
my callback method before working with some GUI controls? Won't it always be
required since the callback is running on a thread pool thread? I see some
code examples of asynch calling and the examples usually have an
InvokeRequired check in the callback before doing any GUI work. It just
seems that that call wouldn't be necessary.

Thanks.
 
B

Bruce Wood

Flack said:
Hello,

If I understand BeginInvoke correctly, when it is called your delegate is
run on a thread pool thread. Now, if you supplied a callback delegate, that
too is called on the same thread pool thread.

My question is this: Do I ever need to check the value of InvokeRequired in
my callback method before working with some GUI controls? Won't it always be
required since the callback is running on a thread pool thread? I see some
code examples of asynch calling and the examples usually have an
InvokeRequired check in the callback before doing any GUI work. It just
seems that that call wouldn't be necessary.

I think that the call is there just for the sake of flexibility. If
some future modification calls the callback method on the UI thread,
then this avoids an attempt to Invoke to the UI thread when it's not
needed.

BTW, I believe that you have the idea of BeginInvoke / Invoke backward.
You use the Thread class or QueueUserWorkItem to start a delegate
running on a background thread. If that delegate calls its callback
delegate using Invoke or BeginInvoke then the callback delegate runs on
the UI thread. If, on the other hand, that delegate calls its callback
delegate directly, and the callback delegate wants to manipulate UI
controls, it must in turn invoke another method using Invoke or
BeginInvoke.

In other words:

1. Code in UI thread invokes delegate to run in the background using,
say, QueueUserWorkItem.
Then, either:
2a. Background method completes and invokes callback delegate using
Invoke or BeginInvoke.
3a. Callback delegate runs on UI thread.
Or:
2b. Background method completes and calls callback delegate directly.
3b. Callback delegate calls another method using Invoke or BeginInvoke
4b. That method runs on UI thread.

You might want to read Jon Skeet's excellent article on threading.
There's a section on threading in Windows Forms:

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

As well, I'm sure that if I've given you bad information, someone
(probably Jon) will jump in and correct me... :)
 
M

Marc Gravell

You should really separate Delegate.BeginInvoke or Control.BeginInvoke;
it isn't clear which you mean (I'm reading it as Delegate.BeginInvoke).

Delegate.BeginInvoke (i.e. BeginInvoke called on a delegate instance)
pushes the work onto a background thread (similar to ThreadPool or
Thread usage) - however Control.BeginInvoke pushes the work to the UI
thread.

As for "is it necessary", first recall that callbacks aren't the only
issue here; some event handlers (etc) can fire on any thread - e.g
System.Timers.Timer.

A lot of code tends to do something like:

void SomeMethod([some signature]) {
if(InvokeRequired) {
// Invoke/BeginInvoke to SomeMethod
} else {
// do the actual work
}
}

So actually, SomeMethod gets called twice; once on a pool thread, once
on the UI. So yes, in this case it is absolutely necessary. If is also
useful to help shortcut when things are happening on the UI thread; in
a highly threaded environment it can be useful to be thread-aware
(agnostic?), so that *however* it happens, it works.

Marc
 

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