ClientBase.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 / ServiceModel / System / ServiceModel / ClientBase.cs / 1 / ClientBase.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
using System.ServiceModel.Diagnostics;
using System.ServiceModel; 
using System.ServiceModel.Channels;
using System.ServiceModel.Description; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Threading; 
using System.ComponentModel;

namespace System.ServiceModel
{ 
    public abstract class ClientBase : ICommunicationObject, IDisposable
        where TChannel : class 
    { 
        TChannel channel = null;
        ChannelFactoryRef channelFactoryRef; 
        EndpointTrait endpointTrait;

        // Determine whether the proxy can share factory with others. It is false only if the public getters
        // are invoked. 
        bool canShareFactory = true;
 
        // Determine whether the proxy is currently holding a cached factory 
        bool useCachedFactory;
 
        // Determine whether we have locked down sharing for this proxy. This is turned on only when the channel
        // is created.
        bool sharingFinalized;
 
        // Determine whether the ChannelFactoryRef has been released. We should release it only once per proxy
        bool channelFactoryRefReleased; 
 
        // Determine whether we have released the last ref count of the ChannelFactory so that we could abort it when it was closing.
        bool releasedLastRef; 

        object syncRoot = new object();

        object finalizeLock = new object(); 

        // Cache at most 32 ChannelFactories 
        static ChannelFactoryRefCache factoryRefCache = new ChannelFactoryRefCache(32); 
        static object staticLock = new object();
 
        static AsyncCallback onAsyncCallCompleted = DiagnosticUtility.Utility.ThunkCallback(new AsyncCallback(OnAsyncCallCompleted));

        // IMPORTANT: any changes to the set of protected .ctors of this class need to be reflected
        // in ServiceContractGenerator.cs as well. 

        protected ClientBase() 
        { 
            endpointTrait = new EndpointTrait("*", null, null);
            InitializeChannelFactoryRef(); 
        }

        protected ClientBase(string endpointConfigurationName)
        { 
            if (endpointConfigurationName == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName"); 
 
            endpointTrait = new EndpointTrait(endpointConfigurationName, null, null);
            InitializeChannelFactoryRef(); 
        }
        protected ClientBase(string endpointConfigurationName, string remoteAddress)
        {
            if (endpointConfigurationName == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
            if (remoteAddress == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress"); 

            endpointTrait = new EndpointTrait(endpointConfigurationName, 
                 new EndpointAddress(remoteAddress), null);
            InitializeChannelFactoryRef();
        }
        protected ClientBase(string endpointConfigurationName, EndpointAddress remoteAddress) 
        {
            if (endpointConfigurationName == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName"); 
            if (remoteAddress == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress"); 

            endpointTrait = new EndpointTrait(endpointConfigurationName, remoteAddress, null);
            InitializeChannelFactoryRef();
        } 
        protected ClientBase(Binding binding, EndpointAddress remoteAddress)
        { 
            if (binding == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
            if (remoteAddress == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");

            channelFactoryRef = new ChannelFactoryRef(new ChannelFactory(binding, remoteAddress));
 
            channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
            TryDisableSharing(); 
        } 

        protected ClientBase(InstanceContext callbackInstance) 
        {
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
 
            endpointTrait = new EndpointTrait("*", null, callbackInstance);
            InitializeChannelFactoryRef(); 
        } 
        protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName)
        { 
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
            if (endpointConfigurationName == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName"); 

            endpointTrait = new EndpointTrait(endpointConfigurationName, null, callbackInstance); 
            InitializeChannelFactoryRef(); 
        }
        protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress) 
        {
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
            if (endpointConfigurationName == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
            if (remoteAddress == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress"); 

            endpointTrait = new EndpointTrait(endpointConfigurationName, new EndpointAddress(remoteAddress), callbackInstance); 
            InitializeChannelFactoryRef();
        }
        protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress)
        { 
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance"); 
            if (endpointConfigurationName == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
            if (remoteAddress == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");

            endpointTrait = new EndpointTrait(endpointConfigurationName, remoteAddress, callbackInstance);
            InitializeChannelFactoryRef(); 
        }
        protected ClientBase(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress) 
        { 
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance"); 
            if (binding == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
            if (remoteAddress == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress"); 

            channelFactoryRef = new ChannelFactoryRef( 
                new DuplexChannelFactory(callbackInstance, binding, remoteAddress)); 
            channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
            TryDisableSharing(); 
        }

        protected T GetDefaultValueForInitialization()
        { 
            return default(T);
        } 
 
        object ThisLock
        { 
            get
            {
                return syncRoot;
            } 
        }
 
        protected TChannel Channel 
        {
            get 
            {
                // created on demand, so that Mort can modify .Endpoint before calling methods on the client
                if (this.channel == null)
                { 
                    lock (ThisLock)
                    { 
                        if (this.channel == null) 
                        {
                            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null) 
                            {
                                if (DiagnosticUtility.ShouldUseActivity)
                                {
                                    ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityOpenClientBase, typeof(TChannel).FullName), ActivityType.OpenClient); 
                                }
 
                                if (this.useCachedFactory) 
                                {
                                    try 
                                    {
                                        CreateChannelInternal();
                                    }
#pragma warning suppress 56500 // covered by FxCOP 
                                    catch (Exception ex)
                                    { 
                                        if (this.useCachedFactory && 
                                            (ex is CommunicationException ||
                                            ex is ObjectDisposedException || 
                                            ex is TimeoutException))
                                        {
                                            DiagnosticUtility.ExceptionUtility.TraceHandledException(ex, TraceEventType.Warning);
                                            InvalidateCacheAndCreateChannel(); 
                                        }
                                        else 
                                        { 
#pragma warning suppress 56503 // [....], We throw only for unknown exceptions.
                                            throw; 
                                        }
                                    }
                                }
                                else 
                                {
                                    CreateChannelInternal(); 
                                } 
                            }
                        } 
                    }
                }
                return channel;
            } 
        }
 
        public ChannelFactory ChannelFactory 
        {
            get 
            {
                TryDisableSharing();
                return GetChannelFactory();
            } 
        }
 
        public ClientCredentials ClientCredentials 
        {
            get 
            {
                TryDisableSharing();
                return this.ChannelFactory.Credentials;
            } 
        }
 
        public CommunicationState State 
        {
            get 
            {
                IChannel channel = (IChannel)this.channel;
                if (channel != null)
                { 
                    return channel.State;
                } 
                else 
                    return CommunicationState.Created;
            } 
        }

        public IClientChannel InnerChannel
        { 
            get
            { 
                return (IClientChannel)Channel; 
            }
        } 

        public ServiceEndpoint Endpoint
        {
            get 
            {
                TryDisableSharing(); 
                return GetChannelFactory().Endpoint; 
            }
        } 

        public void Open()
        {
            ((ICommunicationObject)this).Open(GetChannelFactory().InternalOpenTimeout); 
        }
 
        public void Abort() 
        {
            IChannel channel = (IChannel)this.channel; 
            if (channel != null)
            {
                channel.Abort();
            } 

            if (!channelFactoryRefReleased) 
            { 
                lock (staticLock)
                { 
                    if (!channelFactoryRefReleased)
                    {
                        if (this.channelFactoryRef.Release())
                        { 
                            this.releasedLastRef = true;
                        } 
 
                        channelFactoryRefReleased = true;
                    } 
                }
            }

            // Abort the ChannelFactory if we released the last one. We should be able to abort it when another thread is closing it. 
            if (this.releasedLastRef)
            { 
                this.channelFactoryRef.Abort(); 
            }
        } 

        public void Close()
        {
            ((ICommunicationObject)this).Close(GetChannelFactory().InternalCloseTimeout); 
        }
 
        public void DisplayInitializationUI() 
        {
            ((IClientChannel)this.InnerChannel).DisplayInitializationUI(); 
        }

        void CreateChannelInternal()
        { 
            try
            { 
                this.channel = this.CreateChannel(); 
                if (this.sharingFinalized)
                { 
                    if (this.canShareFactory && !this.useCachedFactory)
                    {
                        // It is OK to add ChannelFactory to the cache now.
                        TryAddChannelFactoryToCache(); 
                    }
                } 
            } 
            finally
            { 
                if (!this.sharingFinalized)
                {
                    // this.CreateChannel() is not called. For safety, we disable sharing.
                    TryDisableSharing(); 
                }
            } 
        } 

        protected virtual TChannel CreateChannel() 
        {
            if (this.sharingFinalized)
                return GetChannelFactory().CreateChannel();
 
            lock (this.finalizeLock)
            { 
                this.sharingFinalized = true; 
                return GetChannelFactory().CreateChannel();
            } 
        }

        void IDisposable.Dispose()
        { 
            this.Close();
        } 
 
        void ICommunicationObject.Open(TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            if (!this.useCachedFactory)
            {
                GetChannelFactory().Open(timeoutHelper.RemainingTime()); 
            }
 
            this.InnerChannel.Open(timeoutHelper.RemainingTime()); 
        }
 
        void ICommunicationObject.Close(TimeSpan timeout)
        {
            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
            { 
                if (DiagnosticUtility.ShouldUseActivity)
                { 
                    ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityCloseClientBase, typeof(TChannel).FullName), ActivityType.Close); 
                }
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 

                if (this.channel != null)
                    InnerChannel.Close(timeoutHelper.RemainingTime());
 
                if (!channelFactoryRefReleased)
                { 
                    lock (staticLock) 
                    {
                        if (!channelFactoryRefReleased) 
                        {
                            if (this.channelFactoryRef.Release())
                            {
                                this.releasedLastRef = true; 
                            }
 
                            this.channelFactoryRefReleased = true; 
                        }
                    } 

                    // Close the factory outside of the lock so that we can abort from a different thread.
                    if (this.releasedLastRef)
                    { 
                        if (this.useCachedFactory)
                        { 
                            this.channelFactoryRef.Abort(); 
                        }
                        else 
                        {
                            this.channelFactoryRef.Close(timeoutHelper.RemainingTime());
                        }
                    } 
                }
            } 
        } 

        event EventHandler ICommunicationObject.Closed 
        {
            add
            {
                this.InnerChannel.Closed += value; 
            }
            remove 
            { 
                this.InnerChannel.Closed -= value;
            } 
        }

        event EventHandler ICommunicationObject.Closing
        { 
            add
            { 
                this.InnerChannel.Closing += value; 
            }
            remove 
            {
                this.InnerChannel.Closing -= value;
            }
        } 

        event EventHandler ICommunicationObject.Faulted 
        { 
            add
            { 
                this.InnerChannel.Faulted += value;
            }
            remove
            { 
                this.InnerChannel.Faulted -= value;
            } 
        } 

        event EventHandler ICommunicationObject.Opened 
        {
            add
            {
                this.InnerChannel.Opened += value; 
            }
            remove 
            { 
                this.InnerChannel.Opened -= value;
            } 
        }

        event EventHandler ICommunicationObject.Opening
        { 
            add
            { 
                this.InnerChannel.Opening += value; 
            }
            remove 
            {
                this.InnerChannel.Opening -= value;
            }
        } 

        IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state) 
        { 
            return ((ICommunicationObject)this).BeginClose(GetChannelFactory().InternalCloseTimeout, callback, state);
        } 

        IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new ChainedAsyncResult(timeout, callback, state, BeginChannelClose, EndChannelClose, BeginFactoryClose, EndFactoryClose); 
        }
 
        void ICommunicationObject.EndClose(IAsyncResult result) 
        {
            ChainedAsyncResult.End(result); 
        }

        IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state)
        { 
            return ((ICommunicationObject)this).BeginOpen(GetChannelFactory().InternalOpenTimeout, callback, state);
        } 
 
        IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return new ChainedAsyncResult(timeout, callback, state, BeginFactoryOpen, EndFactoryOpen, BeginChannelOpen, EndChannelOpen);
        }

        void ICommunicationObject.EndOpen(IAsyncResult result) 
        {
            ChainedAsyncResult.End(result); 
        } 

        //ChainedAsyncResult methods for opening and closing ChannelFactory 

        internal IAsyncResult BeginFactoryOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            if (this.useCachedFactory) 
            {
                return new CompletedAsyncResult(callback, state); 
            } 
            else
            { 
                return GetChannelFactory().BeginOpen(timeout, callback, state);
            }
        }
 
        internal void EndFactoryOpen(IAsyncResult result)
        { 
            if (this.useCachedFactory) 
            {
                CompletedAsyncResult.End(result); 
            }
            else
            {
                GetChannelFactory().EndOpen(result); 
            }
        } 
 
        internal IAsyncResult BeginChannelOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return this.InnerChannel.BeginOpen(timeout, callback, state);
        }

        internal void EndChannelOpen(IAsyncResult result) 
        {
            this.InnerChannel.EndOpen(result); 
        } 

        internal IAsyncResult BeginFactoryClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            if (this.useCachedFactory)
            {
                return new CompletedAsyncResult(callback, state); 
            }
            else 
            { 
                return GetChannelFactory().BeginClose(timeout, callback, state);
            } 
        }

        internal void EndFactoryClose(IAsyncResult result)
        { 
            if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
            { 
                CompletedAsyncResult.End(result); 
            }
            else 
            {
                GetChannelFactory().EndClose(result);
            }
        } 

        internal IAsyncResult BeginChannelClose(TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            if (this.channel != null)
            { 
                return this.InnerChannel.BeginClose(timeout, callback, state);
            }
            else
            { 
                return new CompletedAsyncResult(callback, state);
            } 
        } 

        internal void EndChannelClose(IAsyncResult result) 
        {
            if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
            {
                CompletedAsyncResult.End(result); 
            }
            else 
            { 
                this.InnerChannel.EndClose(result);
            } 
        }

        ChannelFactory GetChannelFactory()
        { 
            return this.channelFactoryRef.ChannelFactory;
        } 
 
        void InitializeChannelFactoryRef()
        { 
            DiagnosticUtility.DebugAssert(this.channelFactoryRef == null, "The channelFactory should have never been assigned");
            DiagnosticUtility.DebugAssert(this.canShareFactory, "GetChannelFactoryFromCache can be called only when canShareFactory is true");
            lock (staticLock)
            { 
                ChannelFactoryRef factoryRef;
                if (factoryRefCache.TryGetValue(this.endpointTrait, out factoryRef)) 
                { 
                    if (factoryRef.ChannelFactory.State != CommunicationState.Opened)
                    { 
                        // Remove the bad ChannelFactory.
                        factoryRefCache.Remove(this.endpointTrait);
                    }
                    else 
                    {
                        this.channelFactoryRef = factoryRef; 
                        this.channelFactoryRef.AddRef(); 
                        useCachedFactory = true;
                        return; 
                    }
                }
            }
 
            if (this.channelFactoryRef == null)
            { 
                // Creating the ChannelFactory at initial time to catch configuration exception earlier. 
                this.channelFactoryRef = CreateChannelFactoryRef(this.endpointTrait);
            } 
        }

        static ChannelFactoryRef CreateChannelFactoryRef(EndpointTrait endpointTrait)
        { 
            DiagnosticUtility.DebugAssert(endpointTrait != null, "The endpointTrait should not be null when the factory can be shared.");
 
            ChannelFactory channelFactory = endpointTrait.CreateChannelFactory(); 
            channelFactory.TraceOpenAndClose = false;
            return new ChannelFactoryRef(channelFactory); 
        }

        // Once the channel is created, we can't disable caching.
        void TryDisableSharing() 
        {
            if (this.sharingFinalized) 
                return; 

            lock (this.finalizeLock) 
            {
                if (this.sharingFinalized)
                    return;
 
                this.canShareFactory = false;
                this.sharingFinalized = true; 
 
                if (this.useCachedFactory)
                { 
                    ChannelFactoryRef pendingFactoryRef = this.channelFactoryRef;
                    this.channelFactoryRef = CreateChannelFactoryRef(this.endpointTrait);
                    this.useCachedFactory = false;
 
                    lock (staticLock)
                    { 
                        if (!pendingFactoryRef.Release()) 
                        {
                            pendingFactoryRef = null; 
                        }
                    }

                    if (pendingFactoryRef != null) 
                        pendingFactoryRef.Abort();
                } 
            } 
        }
 
        void TryAddChannelFactoryToCache()
        {
            DiagnosticUtility.DebugAssert(this.canShareFactory, "This should be called only when this proxy can share ChannelFactory.");
            DiagnosticUtility.DebugAssert(this.channelFactoryRef.ChannelFactory.State == CommunicationState.Opened, 
                "The ChannelFactory must be in Opened state for caching.");
 
            // Lock the cache and add the item to synchronize with lookup. 
            lock (staticLock)
            { 
                ChannelFactoryRef cfRef;
                if (!factoryRefCache.TryGetValue(this.endpointTrait, out cfRef))
                {
                    // Increment the ref count before adding to the cache. 
                    this.channelFactoryRef.AddRef();
                    factoryRefCache.Add(this.endpointTrait, this.channelFactoryRef); 
                    this.useCachedFactory = true; 
                }
            } 
        }

        // NOTE: This should be called inside ThisLock
        void InvalidateCacheAndCreateChannel() 
        {
            RemoveFactoryFromCache(); 
            TryDisableSharing(); 
            CreateChannelInternal();
        } 

        void RemoveFactoryFromCache()
        {
            lock (staticLock) 
            {
                ChannelFactoryRef factoryRef; 
                if (factoryRefCache.TryGetValue(this.endpointTrait, out factoryRef)) 
                {
                    if (object.ReferenceEquals(this.channelFactoryRef, factoryRef)) 
                    {
                        factoryRefCache.Remove(this.endpointTrait);
                    }
                } 
            }
        } 
 
        // WARNING: changes in the signature/name of the following delegates must be applied to the
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code. 
        protected delegate IAsyncResult BeginOperationDelegate(object[] inValues, AsyncCallback asyncCallback, object state);
        protected delegate object[] EndOperationDelegate(IAsyncResult result);

        // WARNING: Any changes in the signature/name of the following type and its ctor must be applied to the 
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
        protected class InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs 
        { 
            object[] results;
 
            internal InvokeAsyncCompletedEventArgs(object[] results, Exception error, bool cancelled, object userState)
                : base(error, cancelled, userState)
            {
                this.results = results; 
            }
 
            public object[] Results 
            {
                get 
                {
                    return this.results;
                }
            } 
        }
 
        // WARNING: Any changes in the signature/name of the following method ctor must be applied to the 
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
        protected void InvokeAsync(BeginOperationDelegate beginOperationDelegate, object[] inValues, 
            EndOperationDelegate endOperationDelegate, SendOrPostCallback operationCompletedCallback, object userState)
        {
            if (beginOperationDelegate == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("beginOperationDelegate");
            } 
            if (endOperationDelegate == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endOperationDelegate"); 
            }

            AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(userState);
            AsyncOperationContext context = new AsyncOperationContext(asyncOperation, endOperationDelegate, operationCompletedCallback); 

            Exception error = null; 
            object[] results = null; 
            IAsyncResult result = null;
            try 
            {
                result = beginOperationDelegate(inValues, onAsyncCallCompleted, context);
                if (result.CompletedSynchronously)
                { 
                    results = endOperationDelegate(result);
                } 
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                {
                    throw;
                } 
                error = e;
            } 
 
            if (error != null || result.CompletedSynchronously) /* result cannot be null if error == null */
            { 
                CompleteAsyncCall(context, results, error);
            }
        }
 
        static void OnAsyncCallCompleted(IAsyncResult result)
        { 
            if (result.CompletedSynchronously) 
            {
                return; 
            }

            AsyncOperationContext context = (AsyncOperationContext)result.AsyncState;
            Exception error = null; 
            object[] results = null;
            try 
            { 
                results = context.EndDelegate(result);
            } 
            catch (Exception e)
            {
                if (DiagnosticUtility.IsFatal(e))
                { 
                    throw;
                } 
 
                error = e;
            } 

            CompleteAsyncCall(context, results, error);
        }
 
        static void CompleteAsyncCall(AsyncOperationContext context, object[] results, Exception error)
        { 
            if (context.CompletionCallback != null) 
            {
                InvokeAsyncCompletedEventArgs e = new InvokeAsyncCompletedEventArgs(results, error, false, context.AsyncOperation.UserSuppliedState); 
                context.AsyncOperation.PostOperationCompleted(context.CompletionCallback, e);
            }
            else
            { 
                context.AsyncOperation.OperationCompleted();
            } 
        } 

        class AsyncOperationContext 
        {
            AsyncOperation asyncOperation;
            EndOperationDelegate endDelegate;
            SendOrPostCallback completionCallback; 

            internal AsyncOperationContext(AsyncOperation asyncOperation, EndOperationDelegate endDelegate, SendOrPostCallback completionCallback) 
            { 
                this.asyncOperation = asyncOperation;
                this.endDelegate = endDelegate; 
                this.completionCallback = completionCallback;
            }

            internal AsyncOperation AsyncOperation 
            {
                get 
                { 
                    return this.asyncOperation;
                } 
            }

            internal EndOperationDelegate EndDelegate
            { 
                get
                { 
                    return this.endDelegate; 
                }
            } 

            internal SendOrPostCallback CompletionCallback
            {
                get 
                {
                    return this.completionCallback; 
                } 
            }
        } 
    }
}

// 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