Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using delegates between main/sub threads

1 view
Skip to first unread message

Pixel.to.life

unread,
May 6, 2008, 4:08:27 PM5/6/08
to
Dear All,

Here is a problem I am facing (it might be too simple, but then I
admit I am not a Guru:-)

I have a main thread, in managed C++, that deals with displaying a
form and some controls.

I invoke another thread for some processing from this thread, so
basically the main thread is waiting on the sub thread.

Now the sub-thread has to keep posting its progress to the main
thread. I have a delegate mechanism for that. So using mutex, I update
the progress variable in the sub-thread's scope, and then invoke the
main thread's delegate method to display the progress.

The problem is just when the delegate is invoked. Control switches
form sub to main thread. But main thread is already waiting for the
sub thread to finish, so it deadlocks right there.

Any ideas/suggestions? The solution seems simple, just that I dont get
it yet.

Thanks!

Jon Skeet [C# MVP]

unread,
May 6, 2008, 4:21:47 PM5/6/08
to
Pixel.to.life <pixel....@gmail.com> wrote:
> Here is a problem I am facing (it might be too simple, but then I
> admit I am not a Guru:-)
>
> I have a main thread, in managed C++, that deals with displaying a
> form and some controls.
>
> I invoke another thread for some processing from this thread, so
> basically the main thread is waiting on the sub thread.

That's your problem - don't make the main thread wait. The point of
using other threads to do work in a UI application is to avoid the UI
locking up. You need to keep the UI event loop free to handle things
like screen refreshes.

--
Jon Skeet - <sk...@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

Pixel.to.life

unread,
May 6, 2008, 5:52:38 PM5/6/08
to
On May 6, 1:21 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:

Thanks Jon.

I realised it after I posted.

Fow now I use WaitForSingleThread(..) API to wait on the sub thread.
Whats the alternative so the sub thread processing can be done
asynchronously?

I am looking at MsgWaitForMultipleObjects(..) instead to see if I can
get status right there.

Sorry I am a novice to multithreading with GUI.

Pixel.to.life

unread,
May 6, 2008, 5:54:14 PM5/6/08
to
On May 6, 1:21 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:

Also, I need to wait for the sub thread because the main thread has to
do some consilidation once the sub thread is done. If I remove the
WaitForSingleThread(...) call, how do I know the subthread is done?

Thanks.

Jon Skeet [C# MVP]

unread,
May 6, 2008, 6:13:57 PM5/6/08
to
Pixel.to.life <pixel....@gmail.com> wrote:
> Also, I need to wait for the sub thread because the main thread has to
> do some consilidation once the sub thread is done. If I remove the
> WaitForSingleThread(...) call, how do I know the subthread is done?

Get the subthread to post back into the main thread, just as it would
to update the UI - using Control.Invoke or Control.BeginInvoke.

Jon Skeet [C# MVP]

unread,
May 6, 2008, 6:15:10 PM5/6/08
to
Pixel.to.life <pixel....@gmail.com> wrote:
> Fow now I use WaitForSingleThread(..) API to wait on the sub thread.
> Whats the alternative so the sub thread processing can be done
> asynchronously?

Just don't wait at all :) If you need to do something when the other
thread's finished, get it to tell you with a call to
Control.Invoke/BeginInvoke.

> I am looking at MsgWaitForMultipleObjects(..) instead to see if I can
> get status right there.
>
> Sorry I am a novice to multithreading with GUI.

That's okay - it's a tricky topic. I have a brief introduction to
threading here:

http://pobox.com/~skeet/csharp/threads

Pixel.to.life

unread,
May 7, 2008, 4:05:11 PM5/7/08
to
On May 6, 3:15 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:


Thanks a lot, Jon. I finally figured out how to do it. I dont wait,
but let the sub thread work async-ly.. and have it post a message
BeginInvoke() when its done.

I noticed that BeginInvoke() isnt as powerful in having UI refresh its
controls.. and when I use Invoke(), its the same problem as before.
Its blocking kind of.

Thanks again!

Jon Skeet [C# MVP]

unread,
May 7, 2008, 4:46:34 PM5/7/08
to
Pixel.to.life <pixel....@gmail.com> wrote:

<snip>

> I noticed that BeginInvoke() isnt as powerful in having UI refresh its
> controls..

What exactly do you mean?

> and when I use Invoke(), its the same problem as before.
> Its blocking kind of.

No "kind of" about it - it blocks until the delegate has executed in
the UI thread.

Pixel.to.life

unread,
May 7, 2008, 7:01:26 PM5/7/08
to
On May 7, 1:46 pm, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:


Ok I correct myself: Invoke() is blocking exactly until the UI updates
itself.

Jon Skeet [C# MVP]

unread,
May 8, 2008, 1:17:41 AM5/8/08
to
Pixel.to.life <pixel....@gmail.com> wrote:
> Ok I correct myself: Invoke() is blocking exactly until the UI updates
> itself.

I should just apologise for the tone of my previous message - it wasn't
*meant* to sound patronising or impatient, but I suspect it came out
that way. Amazingly enough, I couldn't find the blocking nature on the
Control.Invoke documentation page. It's probably there somewhere,
but...

Peter Duniho

unread,
May 8, 2008, 2:09:16 AM5/8/08
to
On Wed, 07 May 2008 22:17:41 -0700, Jon Skeet [C# MVP] <sk...@pobox.com>
wrote:

> Pixel.to.life <pixel....@gmail.com> wrote:


>> Ok I correct myself: Invoke() is blocking exactly until the UI updates
>> itself.

Minor nit-pick: Invoke() only blocks "until the UI updates itself" if the
delegate being invoked updates the UI. For example, calling Refresh() or
Update().

In most cases, this isn't actually going to be the case. Neither of those
methods, for example, are generally found in well-written applications,
not being necessary. Typically, the invoked method will change some state
represented by the UI, but the act of actually redrawing that new state
visually will happen later. It's entirely possible for Invoke() to return
to the caller before the UI has updated itself.

The blocking behavior of Invoke() is defined to be that it blocks until
the delegate being invoked returns. No blocking longer than that is
guaranteed.

> I should just apologise for the tone of my previous message - it wasn't
> *meant* to sound patronising or impatient, but I suspect it came out
> that way. Amazingly enough, I couldn't find the blocking nature on the
> Control.Invoke documentation page. It's probably there somewhere,
> but...

It seems to me that it's asynchronous operations that would warrant
calling out the specific nature of a method in the docs. IMHO, it's
reasonable to assume that a method is synchronous unless stated
otherwise. In that sense, the docs for Control.Invoke() have no need for
a specific statement that it's synchronous, blocking until the delegate is
done. It's implied, because it's always implied that a method won't
return until whatever that method does is done.

That said, if you're not happy with that implication, there is also the
same implication of synchronous behavior in the description of the return
value. The docs say that Control.Invoke() returns the return value from
the delegate being invoked. Since that return value can't possibly exist
until the delegate has itself returned, that's yet another reason that
it's implied in the docs that the delegate is invoked synchronously.

I don't think that there _is_ an explicit statement as to the
blocking/synchronous nature of Control.Invoke(), but neither do I think
it's really necessary.

Pete

Jon Skeet [C# MVP]

unread,
May 8, 2008, 4:33:55 AM5/8/08
to
On May 8, 7:09 am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

<snip>

> I don't think that there _is_ an explicit statement as to the
> blocking/synchronous nature of Control.Invoke(), but neither do I think
> it's really necessary.

While I agree with your logic suggesting it's not *necessary*, I do
think it would be *useful* - particularly if it also pointed out the
option of using BeginInvoke() for a non-blocking form.

Will suggest it to the MSDN team when I have time...

Jon

Ben Voigt [C++ MVP]

unread,
May 9, 2008, 4:18:09 PM5/9/08
to
> It seems to me that it's asynchronous operations that would warrant
> calling out the specific nature of a method in the docs. IMHO, it's
> reasonable to assume that a method is synchronous unless stated
> otherwise. In that sense, the docs for Control.Invoke() have no need

Rather, it's reasonable to assume that a method is executed on the same
thread unless stated otherwise. Synchronization comes with that behavior.
Once you take away the same thread assumption then synchronization should be
called out explicitly.

> for a specific statement that it's synchronous, blocking until the
> delegate is done. It's implied, because it's always implied that a
> method won't return until whatever that method does is done.

You just pointed out that this frequently isn't the case (updating internal
UI state but the screen isn't updated until Windows sends a WM_PAINT).


Peter Duniho

unread,
May 9, 2008, 4:31:43 PM5/9/08
to
On Fri, 09 May 2008 13:18:09 -0700, Ben Voigt [C++ MVP]
<r...@nospam.nospam> wrote:

>> It seems to me that it's asynchronous operations that would warrant
>> calling out the specific nature of a method in the docs. IMHO, it's
>> reasonable to assume that a method is synchronous unless stated
>> otherwise. In that sense, the docs for Control.Invoke() have no need
>
> Rather, it's reasonable to assume that a method is executed on the same
> thread unless stated otherwise.

I only disagree with that statement inasmuch as you included the word
"rather". I don't see either assumption as mutually exclusive.

> Synchronization comes with that behavior.

Executing on the same thread implies synchronization, yes. But the
converse -- that not executing on the same thread implies lack of
synchronization -- is not true. And so...

> Once you take away the same thread assumption then synchronization
> should be
> called out explicitly.

I wouldn't invest any time or effort trying to convince someone to not add
such a statement to the docs. More detail is often useful. However, I
(obviously) disagree that there's a _need_. A benefit, yes. A need, no.

>> for a specific statement that it's synchronous, blocking until the
>> delegate is done. It's implied, because it's always implied that a
>> method won't return until whatever that method does is done.
>
> You just pointed out that this frequently isn't the case (updating
> internal
> UI state but the screen isn't updated until Windows sends a WM_PAINT).

I have no idea what you mean here. If you use Invoke() to call a method
that updates internal UI state, then when Invoke() returns, you can be
sure that what that method does -- updating internal UI state -- is done.
If the method doesn't send a WM_PAINT, then the question of when the
screen is updated or when a WM_PAINT message might be sent is irrelevant.
That's not what the method being invoked does.

Don't confuse what a method _does_ with what later implications that
activity might have. For example, the question of when a WM_PAINT message
is sent is independent of when a method that updates internal UI state is
done, and this is true whether you call that method directly within the
correct thread, or call it indirectly from another thread using Invoke().

Pete

Ben Voigt [C++ MVP]

unread,
May 9, 2008, 5:35:10 PM5/9/08
to
> I have no idea what you mean here. If you use Invoke() to call a
> method that updates internal UI state, then when Invoke() returns,
> you can be sure that what that method does -- updating internal UI
> state -- is done. If the method doesn't send a WM_PAINT, then the
> question of when the screen is updated or when a WM_PAINT message
> might be sent is irrelevant. That's not what the method being invoked
> does.
> Don't confuse what a method _does_ with what later implications that
> activity might have. For example, the question of when a WM_PAINT
> message is sent is independent of when a method that updates internal
> UI state is done, and this is true whether you call that method
> directly within the correct thread, or call it indirectly from
> another thread using Invoke().

But by this definition, BeginInvoke is also synchronous. It does not do
what the documentation says ("Executes a delegate asynchronously"), it posts
a request into a queue corresponding to the UI thread, then returns. The
future execution of the delegate identified in that request is merely a
"later implication of that activity".

>
> Pete


Peter Duniho

unread,
May 9, 2008, 7:33:15 PM5/9/08
to
On Fri, 09 May 2008 14:35:10 -0700, Ben Voigt [C++ MVP]
<r...@nospam.nospam> wrote:

>> I have no idea what you mean here. If you use Invoke() to call a
>> method that updates internal UI state, then when Invoke() returns,
>> you can be sure that what that method does -- updating internal UI
>> state -- is done. If the method doesn't send a WM_PAINT, then the
>> question of when the screen is updated or when a WM_PAINT message
>> might be sent is irrelevant. That's not what the method being invoked
>> does.
>> Don't confuse what a method _does_ with what later implications that
>> activity might have. For example, the question of when a WM_PAINT
>> message is sent is independent of when a method that updates internal
>> UI state is done, and this is true whether you call that method
>> directly within the correct thread, or call it indirectly from
>> another thread using Invoke().
>
> But by this definition, BeginInvoke is also synchronous.

I can't tell whether you are deliberately or accidently confusing to which
"method" I'm referring, but you are.

Both Invoke() and BeginInvoke() are themselves synchronous. That is,
neither method returns until it's done what it does. All methods are like
this.

However, I'm not talking about those methods. I'm talking about the
method that is invoked by either Invoke() or BeginInvoke(). The docs for
Invoke() don't say that it executes the passed in method asynchronously.
It simply says that it invokes the method on the control's owning thread.

You feel that the fact that the method isn't being invoked on the same
thread that's calling Invoke() means that it's implied that the execution
is asynchronous. While I would be curious if you had an example of some
documentation describing an API that specifically executes a method, does
so asynchronously, and yet the docs don't state that specifically, the
fact is I simply disagree on what's a reasonable assumption or not.

We'll just have to agree to disagree. But in any case, anyone reading the
documentation should be able to follow the logical concusion that, since
Invoke() returns the return value of the method being executed, obviously
it cannot return until that method has itself returned.

> It does not do
> what the documentation says ("Executes a delegate asynchronously"),

It does do exactly that. The use of the word "asychronously" isn't
accidental there. It's specifically being used as a shorthand way of
describing what BeginInvoke() does.

> it posts
> a request into a queue corresponding to the UI thread, then returns. The
> future execution of the delegate identified in that request is merely a
> "later implication of that activity".

That's true. And I wouldn't disagree that the docs would do well to be
more detailed about what BeginInvoke() really is doing. However, the
phrase "executes a delegate asynchronously" is a reasonable approximation
and none of that contradicts what I wrote.

Frankly, I find no productive value in continue to argue about whether the
docs are clear enough or not. If they confuse you, that's fine...please
feel free to suggest to Microsoft that they be improved. There's nothing
wrong with improving documentation, even if they aren't ambiguous as-is.

Pete

0 new messages