Click here to Skip to main content
15,896,111 members
Articles / Programming Languages / C#

Fast Asynchronous Delegates in .NET

Rate me:
Please Sign up or sign in to vote.
4.31/5 (15 votes)
1 Jul 2009CPOL2 min read 52.4K   357   53  
Implementation of delegates which are way faster during async operations than the default delegates in .NET
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace FastInvoke
{
    public delegate T FastInvokeDelegate<T>();

    public static class DelegateExtensions
    {
        public static IAsyncResult BeginInvokeFast<T>(this FastInvokeDelegate<T> del, object state, AsyncCallback callback)
        {
            return new FastInvokeAsyncResult<T>(del, callback, state);
        }

        public static T EndInvokeFast<T>(this FastInvokeDelegate<T> del, IAsyncResult asyncResult)
        {
            var result = asyncResult as FastInvokeAsyncResult<T>;
            if (result == null)
                throw new InvalidOperationException("Wrong async result");
            return result.End();
        }

        private class FastInvokeAsyncResult<T> : IAsyncResult
        {
            private volatile int m_isCompleted; // 0==not complete, 1==complete.
            private ManualResetEvent m_asyncWaitHandle;
            private volatile int m_asyncWaitHandleNeeded = 0; //0 - is not needed, 1 - needed
            private readonly AsyncCallback m_callback;
            private readonly object m_asyncState;
            // To hold the results, exceptional or ordinary.
            private Exception m_exception;
            private T m_result;

            public FastInvokeAsyncResult(FastInvokeDelegate<T> work, AsyncCallback callback, object state)
            {
                m_callback = callback;
                m_asyncState = state;

                Run(work);
            }


            public bool IsCompleted
            {
                get { return (m_isCompleted == 1); }
            }
            public bool CompletedSynchronously
            {
                get { return false; }
            }
            public WaitHandle AsyncWaitHandle
            {
                get
                {
                    if (m_asyncWaitHandleNeeded == 1)
                    {
                        return m_asyncWaitHandle;
                    }
                    m_asyncWaitHandleNeeded = 1;
                    m_asyncWaitHandle = new ManualResetEvent(m_isCompleted == 1);

                    return m_asyncWaitHandle;
                }
            }

            public object AsyncState
            {
                get { return m_asyncState; }
            }

            private void Run(FastInvokeDelegate<T> work)
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    try
                    {
                        m_result = work();
                    }
                    catch (Exception e)
                    {
                        m_exception = e;
                    }
                    finally
                    {
                        m_isCompleted = 1;
                        if (m_asyncWaitHandleNeeded == 1)
                        {
                            m_asyncWaitHandle.Set();
                        }
                        if (m_callback != null)
                            m_callback(this);
                    }
                });
            }

            public T End()
            {
                if (m_isCompleted == 0)
                {
                    AsyncWaitHandle.WaitOne();
                    AsyncWaitHandle.Close();
                }

                if (m_exception != null)
                    throw m_exception;
                return m_result;
            }

        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead bwin Interactive Entertainment AG
Austria Austria
The views expressed in my articles are mine and do not necessarily reflect the views of my employer.

if(youWantToContactMe)
{
SendMessage(string.Format("{0}@{1}.com", "liptchinski_vit", "yahoo"));
}

More info in my LinkedIn profile:
http://www.linkedin.com/in/vitaliyliptchinsky

Comments and Discussions