Re: In asynchronous model, IAsyncResult.AsyncWaitHandle signaled first, or AsyncCallback invoked first?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Morgan Cheng wrote:
I did some googling and find this post
http://www.bluebytesoftware.com/blog/2006/06/12/ImplementingAHighperfIAsyncResultAddendum.aspx.
The correct sequence should be
1) set IsCompleted to true,
2) signal the handle,
3) invoke the callback.

This is reasonable, because the callback function might wait on the
AsyncWaitHandle. If the sequence of 2) & 3) is inverted, it would be a
deadlock.

Only if the same thread that is processing the signaling is used to run the callback. AFAIK, there's no requirement that that's how the async paradigm is implemented. A class implementing the async paradigm could, for example, simply use Delegate.BeginInvoke() to execute the callback.

You mention this at the end of your post, but with the implication that because of the extra thread, that technique wouldn't be used. While it may be true that no implementation of the async paradigm uses Delegate.BeginInvoke(), IMHO the extra thread doesn't prove that to be the case. It's not uncommon at all to make a trade-off for code robustness over performance.

Even the callback doesn't depends on the AsyncWaitHandle, it might be
a time-costing operation, which can delay signaling of
AsyncWaitHandle. And, if other operations depends on AsyncWaitHandle,
they are delayed. That's not good.

See above.

With the help of Lutz Roeder's .Net Reflector, I read the reflected
code of System.Web.Services.Protocols.WebClientAsyncResult, which is a
subclass of IAsyncResult. Its Complete function does in the sequence
as mentioned above.

So, you have found a single example of that implementation. That doesn't tell you whether that's the standard way of implementation.

But let's assume it is. You still cannot rely on this information in any useful way. In fact, this is especially true if the thread setting the handle is the same one on which the callback is executed. Just because the WaitHandle gets set, that doesn't mean that the thread waiting on it will run immediately. It just puts that thread into a runnable state.

So, the thread setting the WaitHandle then goes off an executes the callback. Until that thread exhausts its quantum or hits some sort of wait state itself, the thread waiting on the WaitHandle still isn't going to execute.

So even though the WaitHandle is set before the callback is executed, the _observed_ effect is that the callback is executed _before_ the thread waiting on the WaitHandle.

And you can't even rely on it always getting reversed like this. The order of execution of a thread waiting on the WaitHandle and the callback depends on both the exact implementation of the class implementing the async paradigm, _and_ on the exact timing and sequence of various threads executing or waiting.

So, I refer you back to my previous comment/question:

I'm curious if there's a specific scenario in which
this question came up? It seems like an interesting
enough academic question, but since you would
normally use _either_ the WaitHandle _or_ a callback,
not both together, it's not clear why this would come
up in actual code.

Even if there's a reliable answer to the question you asked (and I'm not convinced there is), it doesn't seem like this is the sort of thing you'd need to know while coding an actual application.

Pete
.



Relevant Pages

  • Re: [patch 1/7] Immediate Values - Architecture Independent Code
    ... static unsigned int stopmachine_num_threads; ... * help our sisters onto their CPUs. ... all the other CPUs will execute the callback concurrently. ...
    (Linux-Kernel)
  • Re: Sockets Beginreceive not working correctly.
    ... the beginrecieve is ignored. ... there's no reason to expect your callback method to be ... BeginReceivewould not normally execute the callback in any case. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Sockets Beginreceive not working correctly.
    ... -- By the time you get to stepping through the code, the second part of your data hasn't yet been sent. ... there's no reason to expect your callback method to be executed. ... BeginReceivewould not normally execute the callback in any case. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: How can I tell if my Ribbon is visible?
    ... Depending on the performance cost of executing the callback, you could do this whenever your event gets triggered, but before you execute your parsing. ... The callback will be executed once your tab is brought into the foreground. ... You can do this approach with any of your controls and callbacks, there is no need to create a special one for it. ...
    (microsoft.public.office.developer.com.add_ins)
  • Re: Asynchronous operations with System.Net.Sockets
    ... Yes, when the Callback is executed, it is executed on a separate thread from ... does the code within the callback execute on that ... > BeginWrite(...) again to write more data BEFORE the first BeginWrite ... and the class queues each write request on a Queue ...
    (microsoft.public.dotnet.framework)