BaseAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / BaseAsyncResult.cs / 2 / BaseAsyncResult.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// query object
//  
//--------------------------------------------------------------------- 

namespace System.Data.Services.Client 
{
    using System;
    using System.Diagnostics;
    using System.IO; 
#if !ASTORIA_LIGHT // Data.Services http stack
    using System.Net; 
#else 
    using System.Data.Services.Http;
#endif 

    /// 
    /// Implementation of IAsyncResult
    ///  
    internal abstract class BaseAsyncResult : IAsyncResult
    { 
        /// Originating object, used to validate End* 
        internal readonly object Source;
 
        /// Originating method on source, to differentiate between different methods from same source
        internal readonly string Method;

        /// User callback passed to Begin* 
        private readonly AsyncCallback userCallback;
 
        /// User state passed to Begin* 
        private readonly object userState;
 
        /// wait handle for user to wait until done
        private System.Threading.ManualResetEvent asyncWait;

        /// Holding exception to throw as a nested exception during to End* 
        private Exception failure;
 
        /// true unless something completes asynchronously 
        private bool completedSynchronously = true;
 
        /// true when really completed for the user
        private bool userCompleted;

        /// true when no more changes are pending, 0 false, 1 completed, 2 aborted 
        private int completed;
 
        /// verify we only invoke the user callback once, 0 false, 1 true 
        private int userNotified;
 
        /// non-zero after End*, 0 false, 1, true
        private int done;

        ///  
        /// ctor
        ///  
        /// source object of async request 
        /// async method name on source object
        /// user callback to invoke when complete 
        /// user state
        internal BaseAsyncResult(object source, string method, AsyncCallback callback, object state)
        {
            Debug.Assert(null != source, "null source"); 
            this.Source = source;
            this.Method = method; 
            this.userCallback = callback; 
            this.userState = state;
        } 

        #region IAsyncResult implmentation - AsyncState, AsyncWaitHandle, CompletedSynchronously, IsCompleted

        /// user state object parameter 
        public object AsyncState
        { 
            get { return this.userState; } 
        }
 
        /// wait handle for when waiting is required
        /// if displayed by debugger, it undesirable to create the WaitHandle
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        public System.Threading.WaitHandle AsyncWaitHandle 
        {
            get 
            { 
                if (null == this.asyncWait)
                {   // delay create the wait handle since the user may never use it 
                    // like asyncWait which will be GC'd, the losers in creating the asyncWait will also be GC'd
                    System.Threading.Interlocked.CompareExchange(ref this.asyncWait, new System.Threading.ManualResetEvent(this.IsCompleted), null);

                    // multi-thread condition 
                    // 1) thread 1 returned IAsyncResult and !IsCompleted so AsyncWaitHandle.WaitOne()
                    // 2) thread 2 signals complete, however thread 1 has retrieved this.completed but not assigned asyncWait 
                    if (this.IsCompleted) 
                    {   // yes, Set may be called multiple times - but user would have to assume ManualResetEvent and call Reset
                        this.asyncWait.Set(); 
                    }
                }

                return this.asyncWait; 
            }
        } 
 
        /// did the result complete synchronously?
        public bool CompletedSynchronously 
        {
            get { return this.completedSynchronously; }
            internal set { this.completedSynchronously = value; }
        } 

        /// is the result complete? 
        public bool IsCompleted 
        {
            get { return this.userCompleted; } 
        }

        /// is the result complete?
        internal bool IsCompletedInternally 
        {
            get { return (0 != this.completed); } 
        } 

        #endregion 

        /// first exception that happened
        internal Exception Failure
        { 
            get { return this.failure; }
        } 
 
        /// 
        /// common handler for EndExecuteBatch & EndSaveChanges 
        /// 
        /// derived type of the AsyncResult
        /// source object of async request
        /// async method name on source object 
        /// the asyncResult being ended
        /// data service response for batch 
        internal static T EndExecute(object source, string method, IAsyncResult asyncResult) where T : BaseAsyncResult 
        {
            Util.CheckArgumentNull(asyncResult, "asyncResult"); 

            T result = (asyncResult as T);
            if ((null == result) || (source != result.Source) || (result.Method != method))
            { 
                throw Error.Argument(Strings.Context_DidNotOriginateAsync, "asyncResult");
            } 
 
            Debug.Assert((result.CompletedSynchronously && result.IsCompleted) || !result.CompletedSynchronously, "CompletedSynchronously && !IsCompleted");
 
            if (!result.IsCompleted)
            {   // if the user doesn't want to wait forever, they should explictly wait on the handle with a timeout
                result.AsyncWaitHandle.WaitOne();
 
                Debug.Assert(result.IsCompleted, "not completed after waiting");
            } 
 
            if (System.Threading.Interlocked.Exchange(ref result.done, 1) != 0)
            { 
                throw Error.Argument(Strings.Context_AsyncAlreadyDone, "asyncResult");
            }

            if (null != result.failure) 
            {
                throw Error.InvalidOperation(Strings.Context_SaveChangesError, result.failure); 
            } 

            return result; 
        }

        /// Set the AsyncWait and invoke the user callback.
        ///  
        /// If the background thread gets a ThreadAbort, the userCallback will never be invoked.
        /// This is why it's generally important to never wait forever, but to have more specific 
        /// time limit.  Also then cancel the operation, to make sure its stopped, to avoid 
        /// multi-threading if your wait time limit was just too short.
        ///  
        internal void HandleCompleted()
        {
            if (Util.DoNotHandleException(this.failure))
            { 
                return;
            } 
 
            if (this.IsCompletedInternally && (System.Threading.Interlocked.Exchange(ref this.userNotified, 1) == 0))
            { 
                try
                {
                    // the CompleteRequest may do additional work which is why
                    // it is important not to signal the user via either the 
                    // IAsyncResult.IsCompleted, IAsyncResult.WaitHandle or the callback
                    this.CompletedRequest(); 
                } 
                catch (Exception ex)
                { 
                    if (this.HandleFailure(ex))
                    {
                        throw;
                    } 
                }
 
                // 1. set IAsyncResult.IsCompleted, otherwise user was 
                // signalled on another thread, but the property may not be true.
                this.userCompleted = true; 

                // 2. signal the wait handle because it can't be first nor can it be last.
                if (null != this.asyncWait)
                { 
                    this.asyncWait.Set();
                } 
 
                // 3. invoke the callback because user may throw an exception and stop any further processing
                if (null != this.userCallback) 
                {   // any exception thrown by user should be "unhandled"
                    // it's possible callback will be invoked while another creates and sets the asyncWait
                    this.userCallback(this);
                } 
            }
        } 
 
        /// Cache the exception that happened on the background thread for the caller of EndSaveChanges.
        /// exception object from background thread 
        /// true if the exception (like StackOverflow or ThreadAbort) should be rethrown
        internal bool HandleFailure(Exception e)
        {
            System.Threading.Interlocked.CompareExchange(ref this.failure, e, null); 
            this.SetCompleted();
            return Util.DoNotHandleException(e); 
        } 

        /// Set the async result as completed. 
        internal void SetCompleted()
        {
            System.Threading.Interlocked.CompareExchange(ref this.completed, 1, 0);
        } 

        /// invoked for derived classes to cleanup before callback is invoked 
        protected abstract void CompletedRequest(); 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// query object
//  
//--------------------------------------------------------------------- 

namespace System.Data.Services.Client 
{
    using System;
    using System.Diagnostics;
    using System.IO; 
#if !ASTORIA_LIGHT // Data.Services http stack
    using System.Net; 
#else 
    using System.Data.Services.Http;
#endif 

    /// 
    /// Implementation of IAsyncResult
    ///  
    internal abstract class BaseAsyncResult : IAsyncResult
    { 
        /// Originating object, used to validate End* 
        internal readonly object Source;
 
        /// Originating method on source, to differentiate between different methods from same source
        internal readonly string Method;

        /// User callback passed to Begin* 
        private readonly AsyncCallback userCallback;
 
        /// User state passed to Begin* 
        private readonly object userState;
 
        /// wait handle for user to wait until done
        private System.Threading.ManualResetEvent asyncWait;

        /// Holding exception to throw as a nested exception during to End* 
        private Exception failure;
 
        /// true unless something completes asynchronously 
        private bool completedSynchronously = true;
 
        /// true when really completed for the user
        private bool userCompleted;

        /// true when no more changes are pending, 0 false, 1 completed, 2 aborted 
        private int completed;
 
        /// verify we only invoke the user callback once, 0 false, 1 true 
        private int userNotified;
 
        /// non-zero after End*, 0 false, 1, true
        private int done;

        ///  
        /// ctor
        ///  
        /// source object of async request 
        /// async method name on source object
        /// user callback to invoke when complete 
        /// user state
        internal BaseAsyncResult(object source, string method, AsyncCallback callback, object state)
        {
            Debug.Assert(null != source, "null source"); 
            this.Source = source;
            this.Method = method; 
            this.userCallback = callback; 
            this.userState = state;
        } 

        #region IAsyncResult implmentation - AsyncState, AsyncWaitHandle, CompletedSynchronously, IsCompleted

        /// user state object parameter 
        public object AsyncState
        { 
            get { return this.userState; } 
        }
 
        /// wait handle for when waiting is required
        /// if displayed by debugger, it undesirable to create the WaitHandle
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        public System.Threading.WaitHandle AsyncWaitHandle 
        {
            get 
            { 
                if (null == this.asyncWait)
                {   // delay create the wait handle since the user may never use it 
                    // like asyncWait which will be GC'd, the losers in creating the asyncWait will also be GC'd
                    System.Threading.Interlocked.CompareExchange(ref this.asyncWait, new System.Threading.ManualResetEvent(this.IsCompleted), null);

                    // multi-thread condition 
                    // 1) thread 1 returned IAsyncResult and !IsCompleted so AsyncWaitHandle.WaitOne()
                    // 2) thread 2 signals complete, however thread 1 has retrieved this.completed but not assigned asyncWait 
                    if (this.IsCompleted) 
                    {   // yes, Set may be called multiple times - but user would have to assume ManualResetEvent and call Reset
                        this.asyncWait.Set(); 
                    }
                }

                return this.asyncWait; 
            }
        } 
 
        /// did the result complete synchronously?
        public bool CompletedSynchronously 
        {
            get { return this.completedSynchronously; }
            internal set { this.completedSynchronously = value; }
        } 

        /// is the result complete? 
        public bool IsCompleted 
        {
            get { return this.userCompleted; } 
        }

        /// is the result complete?
        internal bool IsCompletedInternally 
        {
            get { return (0 != this.completed); } 
        } 

        #endregion 

        /// first exception that happened
        internal Exception Failure
        { 
            get { return this.failure; }
        } 
 
        /// 
        /// common handler for EndExecuteBatch & EndSaveChanges 
        /// 
        /// derived type of the AsyncResult
        /// source object of async request
        /// async method name on source object 
        /// the asyncResult being ended
        /// data service response for batch 
        internal static T EndExecute(object source, string method, IAsyncResult asyncResult) where T : BaseAsyncResult 
        {
            Util.CheckArgumentNull(asyncResult, "asyncResult"); 

            T result = (asyncResult as T);
            if ((null == result) || (source != result.Source) || (result.Method != method))
            { 
                throw Error.Argument(Strings.Context_DidNotOriginateAsync, "asyncResult");
            } 
 
            Debug.Assert((result.CompletedSynchronously && result.IsCompleted) || !result.CompletedSynchronously, "CompletedSynchronously && !IsCompleted");
 
            if (!result.IsCompleted)
            {   // if the user doesn't want to wait forever, they should explictly wait on the handle with a timeout
                result.AsyncWaitHandle.WaitOne();
 
                Debug.Assert(result.IsCompleted, "not completed after waiting");
            } 
 
            if (System.Threading.Interlocked.Exchange(ref result.done, 1) != 0)
            { 
                throw Error.Argument(Strings.Context_AsyncAlreadyDone, "asyncResult");
            }

            if (null != result.failure) 
            {
                throw Error.InvalidOperation(Strings.Context_SaveChangesError, result.failure); 
            } 

            return result; 
        }

        /// Set the AsyncWait and invoke the user callback.
        ///  
        /// If the background thread gets a ThreadAbort, the userCallback will never be invoked.
        /// This is why it's generally important to never wait forever, but to have more specific 
        /// time limit.  Also then cancel the operation, to make sure its stopped, to avoid 
        /// multi-threading if your wait time limit was just too short.
        ///  
        internal void HandleCompleted()
        {
            if (Util.DoNotHandleException(this.failure))
            { 
                return;
            } 
 
            if (this.IsCompletedInternally && (System.Threading.Interlocked.Exchange(ref this.userNotified, 1) == 0))
            { 
                try
                {
                    // the CompleteRequest may do additional work which is why
                    // it is important not to signal the user via either the 
                    // IAsyncResult.IsCompleted, IAsyncResult.WaitHandle or the callback
                    this.CompletedRequest(); 
                } 
                catch (Exception ex)
                { 
                    if (this.HandleFailure(ex))
                    {
                        throw;
                    } 
                }
 
                // 1. set IAsyncResult.IsCompleted, otherwise user was 
                // signalled on another thread, but the property may not be true.
                this.userCompleted = true; 

                // 2. signal the wait handle because it can't be first nor can it be last.
                if (null != this.asyncWait)
                { 
                    this.asyncWait.Set();
                } 
 
                // 3. invoke the callback because user may throw an exception and stop any further processing
                if (null != this.userCallback) 
                {   // any exception thrown by user should be "unhandled"
                    // it's possible callback will be invoked while another creates and sets the asyncWait
                    this.userCallback(this);
                } 
            }
        } 
 
        /// Cache the exception that happened on the background thread for the caller of EndSaveChanges.
        /// exception object from background thread 
        /// true if the exception (like StackOverflow or ThreadAbort) should be rethrown
        internal bool HandleFailure(Exception e)
        {
            System.Threading.Interlocked.CompareExchange(ref this.failure, e, null); 
            this.SetCompleted();
            return Util.DoNotHandleException(e); 
        } 

        /// Set the async result as completed. 
        internal void SetCompleted()
        {
            System.Threading.Interlocked.CompareExchange(ref this.completed, 1, 0);
        } 

        /// invoked for derived classes to cleanup before callback is invoked 
        protected abstract void CompletedRequest(); 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK