Tuesday, June 28, 2005 12:34 AM
DmitryR
Deadlocks in async ASP.NET pages (part 1)
One common mistake has to do with the implementation of CompletedSynchronously property of IAsyncResult. People writing their own classes implementing IAsyncResult need to be careful returning the correct value and neither ‘always true’ nor ‘always false’ is a good idea in most cases. According to the design of the async API pattern, CompletedSynchronously is supposed to be 'true' if the AsynCallback is called from inside the ‘begin’ method, on the same thread. In all other cases CompletedSynchronously must be 'false'. An incorrect value could lead to deadlocks.
The reason for existence of CompletedSynchronously property in IAsyncResult is to allow callers of asynchronous components chain asynchronous operations (completed synchronously) without consuming stack and avoid keeping objects alive longer than needed. Without this knowledge(whether or not an async operation completed synchronously) the caller has to call the next operation from the callback of the previous one:
Caller
Component1.BeginMethod
AsyncCallback
Component1.EndMethod
Component2.BeginMethod
AsyncCallback
Component2.EndMethod
Knowing that an operation completed synchronously, the caller could call the next operation after the begin method of the (synchronously completed) previous operation returns.
Caller
Component1.BeginMethod
AsyncCallback
Component1.EndMethod
Component2.BeginMethod
AsyncCallback
Component2.EndMethod
Sometimes people complete an asynchronous operation synchronously in case of an error starting it. A better approach is to throw an exception from the ‘begin’ method. The rule is that if the asynchronous operation could not be started (as a result of an error) ‘begin’ method should throw.