New event-based asynchronous pattern broken?

R

robert.bjorn

With release 2 of the .NET framework, Microsoft introduced a new
pattern for asynchronous operations. The process for creating a
prime-number computing sample component that utilizes the new pattern
is described here:

http://msdn2.microsoft.com/en-us/library/bz33kx67(VS.80).aspx

In particular, the following is mentioned:

"It is implemented using helper classes from the System.ComponentModel
namespace, which ensures that the component works correctly under any
application model, including ASP.NET, Console applications and Windows
Forms applications."

In addition, there is also a sample for creating a Windows Forms based
client that makes use of this component here:

http://msdn2.microsoft.com/en-us/library/8wy069k1(VS.80).aspx

My understanding of the quoted text is that a Windows Forms application
that makes use of a component with this new pattern, will have the
component's callback methods called on the thread that launched the
asynchronous operation, eliminating the need to Invoke(). My
understanding is further that this will similarly solve the problem
with console-based applications, ensuring that the callbacks are called
on the thread the launched the operation.

Having tested the component and the assorted client application sample,
I can confirm that the ManagedThreadID value reported using a
MessageBox.Show() call in the method that launches a prime number
calculation asynchronously, and the ManagedThreadID value displayed
using a similar call in the callback method called when the calculation
has completed, is the same. In other words, the callback does appear to
be called on the correct thread, with no need for Invoke() before
updating the user interface.

However, when using the component in a console application, the
callback method is in fact called from a thread separate from the one
that launched the asynchronous calculation. In other words, this
pattern does not work as I expected for console applications.

In a way, this makes sense to me -- Windows Forms applications are
managed by the .NET framework, which controls a message pump allowing
it to "take over" callbacks initiated from another thread using the
appropriate mechanisms (like the new asynchronous pattern, or plain old
Invoke()). However, when using a console based application the caller
is always in control of the main thread and there is no obvious way for
a callback method to be called on it, without some explicit method of
relinguishing control.

Is there in fact such a method, or is the new asynchronous pattern
useless for console applications? And if that is the case, is there any
inherent advantage with the new pattern at all compared to using
Invoke() (in the Windows Forms case) or manual management of
asynchronous events in some way (such as a custom message queue for a
console application)?

I have read through the relevant MSDN documentation on the topic and
searched the web and newsgroups, but so far not found an answer to
these questions. I am very puzzled. It looks like Microsoft set out to
solve a common problem with asynchronous operations, yet did not solve
it completely given that it does not appear to work for console
applications.

If someone could help to set the record straight, correct me, or just
make an educated guess as to whether this behaviour is appropriate or
if I might have missed something, then I would be most grateful.

Best Regards,
Robert
 
M

marcus

In other words, this pattern does not work as I expected for console
applications.

I can confirm this by testing two samples of code. One being the code
listen on MSDN and one being code produced on my own. In either case,
the thread that Main was running on differed from both the worker
thread and the callback thread. In some cases, the worker thread and
callback thread would be different, but more often than not they would
be on the same thread.

As I can understand why this would come about (considering the nature
of Windows Forms applications -- message pump et al) I do not
understand why MSDN would, if I may be so bold, lie about the nature of
this pattern. To reiterate what Robert reiterated:
In particular, the following is mentioned:

"It is implemented using helper classes from the System.ComponentModel
namespace, which ensures that the component works correctly under any
application model, including ASP.NET, Console applications and Windows
Forms applications."

Note how it's explained that the component is sure to work correctly
(which I would assume means as expected, thread marshaling and all),
under ANY application model including but not limited to Console
applications. Testing shows that this is not true.
 
R

robert.bjorn

For anyone else who might have wondered about this topic, I have now
read up a little on this in more detail. Although the documentation on
MSDN is disappointingly vague, my current thinking is that the new
pattern and the AsyncOperationManager helper class do not in fact help
in any way to move background callbacks to the main thread for console
applications. It only appears to abstract away the Invoke() call for
Windows Forms applications. So the need for manual synchronization for
console applications seems to remain.
 

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