主线升级到.Net4.5,为了更好的使用await/async。 次线保留.Net4.0
Stone authored at 2016-08-01 23:57:53
5.73 KiB
X
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

#if NET4
namespace System.Runtime.CompilerServices
{
    /// <summary> ±íʾÉú³ÉÆ÷£¬ÓÃÓÚ²»·µ»ØÖµµÄÒì²½·½·¨¡£</summary>
    public struct AsyncVoidMethodBuilder : IAsyncMethodBuilder
    {
        private readonly SynchronizationContext m_synchronizationContext;

        private AsyncMethodBuilderCore m_coreState;

        private object m_objectIdForDebugger;

        private static int s_preventUnobservedTaskExceptionsInvoked;

        private object ObjectIdForDebugger
        {
            get
            {
                if (m_objectIdForDebugger == null)
                {
                    m_objectIdForDebugger = new object();
                }
                return m_objectIdForDebugger;
            }
        }

        static AsyncVoidMethodBuilder()
        {
            try
            {
                PreventUnobservedTaskExceptions();
            }
            catch
            {
            }
        }

        internal static void PreventUnobservedTaskExceptions()
        {
            if (Interlocked.CompareExchange(ref s_preventUnobservedTaskExceptionsInvoked, 1, 0) == 0)
            {
                TaskScheduler.UnobservedTaskException += (s, e) => { e.SetObserved(); };
            }
        }

        /// <summary>´´½¨ÀàʵÀý</summary>
        /// <returns></returns>
        public static AsyncVoidMethodBuilder Create()
        {
            return new AsyncVoidMethodBuilder(SynchronizationContext.Current);
        }

        private AsyncVoidMethodBuilder(SynchronizationContext synchronizationContext)
        {
            m_synchronizationContext = synchronizationContext;
            if (synchronizationContext != null)
            {
                synchronizationContext.OperationStarted();
            }
            m_coreState = default(AsyncMethodBuilderCore);
            m_objectIdForDebugger = null;
        }

        /// <summary>¿ªÊ¼ÔËÐÐÓйØÁª×´Ì¬»úµÄÉú³ÉÆ÷¡£</summary>
        /// <typeparam name="TStateMachine"></typeparam>
        /// <param name="stateMachine"></param>
        [DebuggerStepThrough]
        public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
        {
            m_coreState.Start(ref stateMachine);
        }

        /// <summary>Ò»¸öÉú³ÉÆ÷ÓëÖ¸¶¨µÄ״̬»ú¹ØÁª¡£</summary>
        /// <param name="stateMachine"></param>
        public void SetStateMachine(IAsyncStateMachine stateMachine)
        {
            m_coreState.SetStateMachine(stateMachine);
        }

        void IAsyncMethodBuilder.PreBoxInitialization()
        {
        }

        /// <summary>Ö¸¶¨µÄ awaiter Íê³Éʱ£¬°²ÅÅ״̬»ú£¬ÒÔ¼ÌÐøÏÂÒ»²Ù×÷¡£</summary>
        /// <typeparam name="TAwaiter"></typeparam>
        /// <typeparam name="TStateMachine"></typeparam>
        /// <param name="awaiter"></param>
        /// <param name="stateMachine"></param>
        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
        {
            try
            {
                Action completionAction = m_coreState.GetCompletionAction(ref this, ref stateMachine);
                awaiter.OnCompleted(completionAction);
            }
            catch (Exception exception)
            {
                AsyncServices.ThrowAsync(exception, null);
            }
        }

        /// <summary>Ö¸¶¨µÄ awaiter Íê³Éʱ£¬°²ÅÅ״̬»ú£¬ÒÔ¼ÌÐøÏÂÒ»²Ù×÷¡£´Ë·½·¨¿É´Ó²¿·ÖÊÜÐÅÈεĴúÂëµ÷Óá£</summary>
        /// <typeparam name="TAwaiter"></typeparam>
        /// <typeparam name="TStateMachine"></typeparam>
        /// <param name="awaiter"></param>
        /// <param name="stateMachine"></param>
        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
        {
            try
            {
                Action completionAction = m_coreState.GetCompletionAction(ref this, ref stateMachine);
                awaiter.UnsafeOnCompleted(completionAction);
            }
            catch (Exception exception)
            {
                AsyncServices.ThrowAsync(exception, null);
            }
        }

        /// <summary>±ê¼Ç´Ë·½·¨Éú³ÉÆ÷Ϊ³É¹¦Íê³É¡£</summary>
        public void SetResult()
        {
            if (m_synchronizationContext != null)
            {
                NotifySynchronizationContextOfCompletion();
            }
        }

        /// <summary>½«Ò»¸öÒì³£°ó¶¨µ½¸Ã·½·¨Éú³ÉÆ÷¡£</summary>
        /// <param name="exception"></param>
        public void SetException(Exception exception)
        {
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }
            if (m_synchronizationContext != null)
            {
                try
                {
                    AsyncServices.ThrowAsync(exception, m_synchronizationContext);
                    return;
                }
                finally
                {
                    NotifySynchronizationContextOfCompletion();
                }
            }
            AsyncServices.ThrowAsync(exception, null);
        }

        private void NotifySynchronizationContextOfCompletion()
        {
            try
            {
                m_synchronizationContext.OperationCompleted();
            }
            catch (Exception exception)
            {
                AsyncServices.ThrowAsync(exception, null);
            }
        }
    }
}
#endif