RpcAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / RpcAsyncResult.cs / 1 / RpcAsyncResult.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.Collections; 
    using System.Collections.Specialized; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Threading;
    using Microsoft.Win32.SafeHandles;

    using IDT=Microsoft.InfoCards.Diagnostics.InfoCardTrace; 
    //
    // Summary: 
    // This class is responsible for keeping track of the state of an 
    // asynchronous ui agent rpc.
    // 
    // Remarks:
    // An RpcAysncResult instance is created for each incoming ui agent
    // asynchronous RPC request.  When the request either completes or is
    // cancelled the AsyncWaitHandle property is set.  If a native SafeWaitHandle 
    // corresponding to an Event is passed in, then that is also set.
    // 
    // The thread started to service the asynchronous request should periodically 
    // check the IsCanceled property on the RpcAsyncResult and immediately clean
    // up, complete the request and return if it is true. 
    //
    internal class RpcAsyncResult : IAsyncResult, IDisposable
    {
        // 
        // public delegate type exposed for cancelation callbacks.
        // 
        public delegate void AsyncCancelCallback(); 

        class RpcAsyncHandleDictionary : HandleDictionary< RpcAsyncResult > {} 

        static RpcAsyncHandleDictionary s_handles = new RpcAsyncHandleDictionary();

        static object      s_syncRoot    = new Object(); 

        ClientRequest    m_request;              // The request that this async op is associated with 
        ManualResetEvent m_externEvent;          // A handle to native event to signal when the operation completes. 
        bool             m_isCompleted;
        bool             m_isCanceled; 
        bool             m_isResultPickedUp;
        bool             m_isDisposed;
        object           m_result;
        string           m_opType; 
        ManualResetEvent m_event;
        int              m_handle;               // A unique id that clients use to reference this operation. 
        object           m_syncRoot; 
        Exception        m_exception;            // Any exceptions that occur on the worker thread are stored here.
 

        AsyncCancelCallback   m_cancelCallback;

 
        //
        // Summary: 
        // Constructs a new RpcAsyncResult. 
        //
        // Parameters: 
        // request      - The request this operation is associated with.
        // opType       - The kind of operation that this is.
        // exdternEvent - A native event handle so be signalled when the operation is complete.
        // 
        public RpcAsyncResult( ClientRequest request, string opType, SafeWaitHandle externEvent )
        { 
            IDT.ThrowInvalidArgumentConditional( null == request, "request" ); 

 
            m_syncRoot         = new Object();
            m_request          = request;
            m_opType           = opType;
 
            if( null != externEvent )
            { 
                m_externEvent = new ManualResetEvent( false ); 
                m_externEvent.SafeWaitHandle = externEvent;
            } 

            m_event = new ManualResetEvent( false );

            // 
            // Pick a handle value that is not in use yet.
            // 
            lock( s_syncRoot ) 
            {
                int handle = 0; 

                try
                {
                    handle = s_handles.GetNewHandle(); 
                }
                catch( IndexOutOfRangeException e ) 
                { 
                    throw IDT.ThrowHelperError( new ServiceBusyException( SR.GetString( SR.ServiceTooManyAsyncOperations ,s_handles.MaxSize ), e ) );
                } 

                m_handle = handle;
                s_handles[ m_handle ] = this;
            } 

            m_request.AddAsyncOp( this ); 
        } 

        public AsyncCancelCallback CancelCallback 
        {
            get{ return m_cancelCallback; }
            set{ m_cancelCallback = value; }
        } 

        public WaitHandle AsyncWaitHandle 
        { 
            get { return m_event; }
        } 

        public bool CompletedSynchronously
        {
            get { return false; } 
        }
 
        public object AsyncState 
        {
            get { return null; } 
        }

        //
        // Summary: 
        // Holds the result of the async operation.
        // 
        // Remarks: 
        // This should be an operation specific object type corresponding to the
        // operation that this RpcAsyncResult is for. 
        //
        public object Result
        {
            get 
            {
                IDT.DebugAssert( m_isCompleted || m_isCanceled, "result is neither completed nor cancelled" ); 
 
                return m_result;
            } 
            set
            {
                m_result = value;
            } 
        }
 
        public bool IsCompleted 
        {
            get { return m_isCompleted; } 
        }

        public bool IsCanceled
        { 
            get { return m_isCanceled; }
        } 
 
        public int Handle
        { 
            get { return m_handle; }
        }

        public Exception Exception 
        {
            get { return m_exception; } 
            set { m_exception = value; } 
        }
 
        //
        // Summary:
        // Should be called when the thread working on the async op has completed
        // processing.  Should be called even if the thread completes due to 
        // cancellation.  Causes disposal if the async client has already indicated that it is through with the
        // results. 
        // 
        public void Complete()
        { 
            lock( m_syncRoot )
            {
                IDT.DebugAssert( !m_isCompleted, "result is already completed" );
 
                if( !m_isCompleted )
                { 
                    m_isCompleted = true; 

                    if( !m_isCanceled ) 
                    {
                        AlertWaiters();
                    }
 
                    MaybeDispose();
                } 
            } 

            return; 
        }

        public void Cancel()
        { 
            lock( m_syncRoot )
            { 
                InternalCancel(); 
            }
        } 

        private void InternalCancel()
        {
            if( m_isCanceled || m_isCompleted ) 
            {
                return; 
            } 

            if( null != CancelCallback ) 
            {
                CancelCallback();
            }
 
            m_isCanceled = true;
            AlertWaiters(); 
        } 

        private void AlertWaiters() 
        {
            m_event.Set();

            if( null != m_externEvent ) 
            {
                m_externEvent.Set(); 
            } 
        }
 
        //
        // This must be called with m_syncRoot locked.
        //
        private void MaybeDispose() 
        {
            if( m_isCompleted && m_isResultPickedUp ) 
            { 
                DisposeInternal();
            } 
        }

        //
        // Summary: 
        // Indicates that the async client is done with the request.  Causes disposal if the async op has been
        // completed already.  Otherwise this object will be disposed when the async op has completed. 
        public void Dispose() 
        {
            if ( m_isResultPickedUp ) 
            {
                return;
            }
 
            lock( m_syncRoot )
            { 
                InternalCancel(); 

                m_isResultPickedUp = true; 
                MaybeDispose();
            }
        }
 
        private void DisposeInternal()
        { 
            // 
            // At this point the m_syncRoot lock is held
            // by the caller of MaybeDispose 
            //
            if( !m_isDisposed )
            {
                m_isDisposed = true; 

                m_request.RemoveAsyncOp( this.Handle ); 
                m_request = null; 

                if( null != m_externEvent ) 
                {
                    m_externEvent.Close();
                }
                m_event.Close(); 

                lock( s_syncRoot ) 
                { 
                    s_handles.Remove( this.Handle );
                } 
            }
        }
    }
} 

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

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