Welcome to MSDN Blogs Sign in | Join | Help

A Generic IAsyncResult Implementation

Lately, I've found myself writing implementations of IAsyncResult more than once, and as it turns out, all of those implementations have been so similar that I have ended up creating a generic implementation.

When implementing the Async Pattern, you can often get by with using a delegate as described in the design guidelines, and in this case, you don't need to implement IAsyncResult yourself. However, there will be cases where a custom implementation of IAsyncResult may be necessary. In some cases, the folllowing class may be suitable to your needs.

Update: Oleg Mikhailik has been so kind to point out some flaws of the code I first posted (see the comments), so I've decided to update the post with a new version of the code. Again, whether such an implementation is suitable for you depends on your needs. The main point of this post is give an example implementation of IAsyncResult, since so few are available, so this is not an authoritative, general-purpose implementation.

internal class AsyncResult<T> : IAsyncResult, IDisposable
{
    private readonly AsyncCallback callback_;
    private bool completed_;
    private bool completedSynchronously_;
    private readonly object asyncState_;
    private readonly ManualResetEvent waitHandle_;
    private T result_;
    private Exception e_;
    private readonly object syncRoot_;
 
    internal AsyncResult(AsyncCallback cb, object state)
        : this(cb, state, false)
    {
    }
 
    internal AsyncResult(AsyncCallback cb, object state,
        bool completed)
    {
        this.callback_ = cb;
        this.asyncState_ = state;
        this.completed_ = completed;
        this.completedSynchronously_ = completed;
 
        this.waitHandle_ = new ManualResetEvent(false);
        this.syncRoot_ = new object();
    }
 
    #region IAsyncResult Members
 
    public object AsyncState
    {
        get { return this.asyncState_; }
    }
 
    public WaitHandle AsyncWaitHandle
    {
        get { return this.waitHandle_; }
    }
 
    public bool CompletedSynchronously
    {
        get 
        {
            lock (this.syncRoot_)
            {
                return this.completedSynchronously_;
            }
        }
    }
 
    public bool IsCompleted
    {
        get 
        {
            lock (this.syncRoot_)
            {
                return this.completed_;
            }
        }
    }
 
    #endregion
 
    #region IDisposable Members
 
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }
 
    #endregion
 
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            lock (this.syncRoot_)
            {
                if (this.waitHandle_ != null)
                {
                    ((IDisposable)this.waitHandle_).Dispose();
                }
            }
        }
    }
 
    internal Exception Exception
    {
        get
        {
            lock (this.syncRoot_)
            {
                return this.e_;
            }
        }
    }
 
    internal T Result
    {
        get 
        {
            lock (this.syncRoot_)
            {
                return this.result_;
            }
        }
    }
 
    internal void Complete(T result,
        bool completedSynchronously)
    {
        lock (this.syncRoot_)
        {
            this.completed_ = true;
            this.completedSynchronously_ =
                completedSynchronously;
            this.result_ = result;
        }
 
        this.SignalCompletion();
    }
 
    internal void HandleException(Exception e,
        bool completedSynchronously)
    {
        lock (this.syncRoot_)
        {
            this.completed_ = true;
            this.completedSynchronously_ =
                completedSynchronously;
            this.e_ = e;
        }
 
        this.SignalCompletion();
    }
 
    private void SignalCompletion()
    {
        this.waitHandle_.Set();
 
        ThreadPool.QueueUserWorkItem(new WaitCallback(this.InvokeCallback));
    }
 
    private void InvokeCallback(object state)
    {
        if (this.callback_ != null)
        {
            this.callback_(this);
        }
    }
}

As reproduced here, you may have noticed that the class is internal. This is because I usually just copy in this code and use it internally, but if you want to include it in a reusable library, you will obviously need to change the class and relevant members (the constructors, Result and Complete) to public.

When implementing the Async Pattern, you can create and return an instance of AsyncResult<T> and return it from your BeginX method. Then, when your asynchronous operation completes, call the Complete method, which will store the result, release the WaitHandle and invoke any callback supplied by the client. To implement the EndX method, cast the incoming IAsyncResult to AsyncResult<T>, call WaitOne on its AsyncWaitHandle and return its Result property.

This is not the only way to implement IAsyncResult, but it has worked well for me in several cases.

Published Friday, February 09, 2007 1:03 PM by ploeh
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: A Generic IAsyncResult Implementation

Friday, February 09, 2007 11:56 AM by mihailik

The most problem here is AsyncWaitHandle. You are creating it even if it might not be used at all.

And not only might, but it most likely will not be used -- the common scenario for IAsyncResult is to fire BeginSomething and then either hope for AsyncCallback to be called, or call EndSomething wich itself blocks.

Considering asynchronous design pattern may be used in performance-sensitive server-based application, you are effectively creating major resource bottleneck. And the only hope is that memory pressure will be high as well, so GC will cleanup all those bazillions of redundant ManualResetEvents.

Recently ago I wrote couple of my own AsyncResult implementations for blocking queue thing, at it actually is VERY VERY non-trivial task.

The key idea to deal with AsyncWaitHandle is to create it on-demand.

The other problem (minor or major depends on the usage of the class) is thread safety. Although full thread safety requirement is not claimed, we definitely cannot be completely non-safe. Changing the completed/incompleted state shall be thread-safe in any case.

I started my class with same design aproach -- generic AsyncResult which holds result and can be used either for synchronous or asynchronous operation (CompletedSynchronously). But it proved to be extermely error-prone path. At the end I've got 2 separate classes, one for synchronously completed operation and one for asynchronously. Synchronously completed operation can be optimised even more aggressive, but the actual goal was not optimisation but clean and safe code.

And one another time, think about thread safety and synchronisation. This cost cannot be passed to QA, it shall be thought through very accurately.

P.S. I am planning to finish with my blocking queue class and enclosing project soon and the code will be posted for public use. But I can send it to any interesting party for review or direct use, without any restrictions.

# re: A Generic IAsyncResult Implementation

Friday, February 09, 2007 12:04 PM by mihailik

My mail is mi98hai12lik@gmail.com (remove digits).

# re: A Generic IAsyncResult Implementation

Friday, February 09, 2007 3:43 PM by ploeh

Hi Mihailik

Thank you for your comment. I think it only demonstrates that my way isn't the only way to do it :)

As it is right now, the class is internal, so it assumes that you use it together with at least one other, public class. If you were to change it to an entirely public class, I agree that more robustness may be required.

Your point about WaitHandle resource usage is valid: It just occurred to me that WaitHandle implements IDisposable, so that should have clued me in on the fact that I should be more conservative about its usage. Incidentally, since AsyncResult<T> has an IDisposable member variable, it should itself implement IDisposable.

At least, this issue should be easy to resolve by implementing the AsyncWaitHandle with lazy initialization, and updating the Complete method accordingly.

I think you are right about the need for thread-safety around at least some of the member variables. I'll see what I can do about that :)

It may be that this implementation of IAsyncResult is not useful in all cases, but then I never claimed that. On the other hand, it has served me well on several occasions. My main motivation for posting this (and thus, sticking my neck out) was that it's actually pretty difficult to find an example implementation of IAsyncResult.

# re: A Generic IAsyncResult Implementation

Sunday, February 18, 2007 10:50 PM by greg

HI..

Im quite interested in seeing how this IAsyncResult would be used in a project.. Im currently implementing my own BeginXXX EndXXX methods and inside i use delgate.beginInvoke with call backs etc.. can this custom IAsyncResult be used with the Delegate.Invoke model? or is it used differently.. Any same projects would be greatly appreciated.  I'm guessing this would be used with a ThreapStart or something along those lines?

# re: A Generic IAsyncResult Implementation

Monday, February 19, 2007 3:24 AM by ploeh

Hi Greg

Thank you for writing. As I wrote in the introduction to my post, you don't need to write a custom implementation of IAsyncResult if you use the delegate approach.

In this case, delegate.BeginInvoke returns an IAsyncResult implementation that you should be able to reuse in your own implementation.

HTH

# re: A Generic IAsyncResult Implementation

Thursday, February 22, 2007 7:23 PM by mrhaboobi

Hi Again.

I've now completed my delegate approach, and as you mentioned a custom iasyncresult is not possible.  Do you have an example using this Generic Iasycn for people that take the Threading approach.. Im going to need to develop some async web services/ handlers and from what i hav found a custom iasyncresult combined with threads is the best way?  im just looking for a tidy implementation example :)

Cheers

# re: A Generic IAsyncResult Implementation

Friday, February 23, 2007 8:59 AM by ploeh

Hi mrhaboobi

Thank you for writing. I'm not sure I understand your need, but maybe this article can help answer some of your questions: http://msdn2.microsoft.com/en-us/library/83bkx91t.aspx

If this doesn't help, you are welcome to write again and explain what you are trying to do.

# re: A Generic IAsyncResult Implementation

Friday, March 09, 2007 7:48 AM by Jakob

You probably already know but Jeffrey Richter has published his generic implementation of IAsyncResult in his Concurrent Affairs column in the March issue of MSDN Magazine: http://msdn.microsoft.com/msdnmag/issues/07/03/ConcurrentAffairs/

Best regards, Jakob.

# re: A Generic IAsyncResult Implementation

Friday, March 09, 2007 7:59 AM by ploeh

Hi Jakob

Yes, someone else was so nice to point that out to me, but in my defense, that article wasn't published when I wrote my post.

I haven't yet had a chance to read the article, but I'm sure Jeffrey Richter's implementation is much better and more correct than mine :)

# IAsyncResult<T> da riutilizzare ...

Sunday, March 11, 2007 6:14 AM by Paolo Pialorsi

Ho trovato questo post sui blogs di MSDN. Fornisce un modello generico di IAsyncResult che in effetti

# re: A Generic IAsyncResult Implementation

Monday, June 04, 2007 10:09 AM by bonbon

I read Jeffrey Richter's implementation, but I don't think it is as useful as yours. Nice job, thx a lot.

# re: A Generic IAsyncResult Implementation

Monday, June 04, 2007 1:31 PM by ploeh

Hi bonbon

Thank you for your praise, but after having read Jeffrey Richter's article, I suspect that his implementation is more lightweight and robust than mine :)

# re: A Generic IAsyncResult Implementation

Monday, June 23, 2008 12:21 AM by Malcolm Hall

dude the first thing you should explain is what this code is for. I was googling for something and your code made no sense to me.

# re: A Generic IAsyncResult Implementation

Wednesday, July 30, 2008 6:21 AM by reisi

Nice looking implementation.. Just why isn't this class included in .NET as a public built-in abstract base class for everyone to use?

There must be some base class for implementing IAsyncResult classes; it wouldn't make any sense if every async method in .NET would have their own..

# re: A Generic IAsyncResult Implementation

Friday, August 01, 2008 3:22 AM by ploeh

Hi reisi

There are no base classes in the BCL for implementing IAsyncResult, but an implementation like Jeffrey Richter's (see comments above) would be a very good candidate.

You can suggest such a class on https://connect.microsoft.com/VisualStudio.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker