473,386 Members | 1,795 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Using delegates between main/sub threads

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!
Jun 27 '08 #1
15 2643
Pixel.to.life <pi***********@gmail.comwrote:
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
Jun 27 '08 #2
On May 6, 1:21*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Pixel.to.life <pixel.to.l...@gmail.comwrote:
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
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.
Jun 27 '08 #3
On May 6, 1:21*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Pixel.to.life <pixel.to.l...@gmail.comwrote:
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
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.
Jun 27 '08 #4
Pixel.to.life <pi***********@gmail.comwrote:
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 - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jun 27 '08 #5
Pixel.to.life <pi***********@gmail.comwrote:
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

--
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
Jun 27 '08 #6
On May 6, 3:15*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Pixel.to.life <pixel.to.l...@gmail.comwrote:
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

--
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

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!
Jun 27 '08 #7
Pixel.to.life <pi***********@gmail.comwrote:

<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.

--
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
Jun 27 '08 #8
On May 7, 1:46*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Pixel.to.life <pixel.to.l...@gmail.comwrote:

<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.

--
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

Ok I correct myself: Invoke() is blocking exactly until the UI updates
itself.
Jun 27 '08 #9
Pixel.to.life <pi***********@gmail.comwrote:
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...

--
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
Jun 27 '08 #10
On Wed, 07 May 2008 22:17:41 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
Pixel.to.life <pi***********@gmail.comwrote:
>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
Jun 27 '08 #11
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
Jun 27 '08 #12
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).
Jun 27 '08 #13
On Fri, 09 May 2008 13:18:09 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>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
Jun 27 '08 #14
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

Jun 27 '08 #15
On Fri, 09 May 2008 14:35:10 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>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
Jun 27 '08 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Coot | last post by:
I've been running many tests of the Asynchronous Delegate technique and I find that although BeginInvoke() does queue the method delegate onto a worker thread, it always does so on the _same_...
2
by: Steve Lutz | last post by:
Hi, I have a simple question that I cannot seem to find the answer to. Let's say my application has 2 threads, a Main thread and a Worker thread. As the worker thread progresses, it send results...
2
by: rb531 | last post by:
Guys, I am struck up with a dilemma whether to use threading or delgates for asynchronous processing. Can anyone throw some light on this? Please let me know which one is better. Thanks
11
by: Doug Thews | last post by:
I've been working on some samples that use BeginInvoke/EndInvoke. In one example, I call BeginInvoke and pass it an AsyncCallback function pointer. I was messing around with ReaderWriterLocks and...
12
by: Grant | last post by:
I am having great difficulty understanding this and any code samples I find online are kilometres long and complicated to understand...Please could someone give me a simple exampe of how to get a...
6
by: Jon Davis | last post by:
I've used delegates fairly heavily for several years in C# for event handling and for starting threads. Does anyone have any real-world scenarios where delegates were both extremely useful and...
0
by: Sebouh | last post by:
Hi guys. I was messing with Threading and stuff, and i have reached a point where i'm not sure what's causing the current behavior. Here's the code: Public Class Form1 Private Sub...
8
by: piercy | last post by:
Ok, I’m new to this oo stuff so it sort of confuses the hell out of me at times.. Anyway, I have my main form which contains 3 panels and the center panel gets populated with 6 user controls. So I’m...
2
by: =?Utf-8?B?QWxwaGFwYWdl?= | last post by:
Hello, I have a class MyWorker. Each time I create a new instance of MyWorker, I queue it to the ThreadPool. So, 1 MyWorker object is pooled and belongs to its thread (there can't have 2...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.