RequestChannel.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 / Channels / RequestChannel.cs / 1 / RequestChannel.cs

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

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.ServiceModel; 
    using System.Diagnostics;
    using System.ServiceModel.Diagnostics; 
    using System.Threading;

    abstract class RequestChannel : ChannelBase, IRequestChannel
    { 
        bool manualAddressing;
        List outstandingRequests = new List(); 
        EndpointAddress to; 
        Uri via;
        ManualResetEvent closedEvent; 
        bool closed;

        protected RequestChannel(ChannelManagerBase channelFactory, EndpointAddress to, Uri via, bool manualAddressing)
            : base(channelFactory) 
        {
            if (!manualAddressing) 
            { 
                if (to == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("to");
                }
            }
 
            this.manualAddressing = manualAddressing;
            this.to = to; 
            this.via = via; 
        }
 
        protected bool ManualAddressing
        {
            get
            { 
                return this.manualAddressing;
            } 
        } 

        public EndpointAddress RemoteAddress 
        {
            get
            {
                return this.to; 
            }
        } 
 
        public Uri Via
        { 
            get
            {
                return this.via;
            } 
        }
 
        protected void AbortPendingRequests() 
        {
            IRequestBase[] requestsToAbort = CopyPendingRequests(false); 

            if (requestsToAbort != null)
            {
                foreach (IRequestBase request in requestsToAbort) 
                {
                    request.Abort(this); 
                } 
            }
        } 

        protected IAsyncResult BeginWaitForPendingRequests(TimeSpan timeout, AsyncCallback callback, object state)
        {
            IRequestBase[] pendingRequests = SetupWaitForPendingRequests(); 
            return new WaitForPendingRequestsAsyncResult(timeout, this, pendingRequests, callback, state);
        } 
 
        protected void EndWaitForPendingRequests(IAsyncResult result)
        { 
            WaitForPendingRequestsAsyncResult.End(result);
        }

        void FinishClose() 
        {
            lock (outstandingRequests) 
            { 
                if (!closed)
                { 
                    closed = true;
                    if (closedEvent != null)
                    {
                        this.closedEvent.Close(); 
                    }
                } 
            } 
        }
 
        IRequestBase[] SetupWaitForPendingRequests()
        {
            return this.CopyPendingRequests(true);
        } 

        protected void WaitForPendingRequests(TimeSpan timeout) 
        { 
            IRequestBase[] pendingRequests = SetupWaitForPendingRequests();
            if (pendingRequests != null) 
            {
                if (!closedEvent.WaitOne(timeout, false))
                {
                    foreach (IRequestBase request in pendingRequests) 
                    {
                        request.Abort(this); 
                    } 
                }
            } 
            FinishClose();
        }

        IRequestBase[] CopyPendingRequests(bool createEventIfNecessary) 
        {
            IRequestBase[] requests = null; 
 
            lock (outstandingRequests)
            { 
                if (outstandingRequests.Count > 0)
                {
                    requests = new IRequestBase[outstandingRequests.Count];
                    outstandingRequests.CopyTo(requests); 
                    outstandingRequests.Clear();
 
                    if (createEventIfNecessary && closedEvent == null) 
                    {
                        closedEvent = new ManualResetEvent(false); 
                    }
                }
            }
 
            return requests;
        } 
 
        protected void FaultPendingRequests()
        { 
            IRequestBase[] requestsToFault = CopyPendingRequests(false);

            if (requestsToFault != null)
            { 
                foreach (IRequestBase request in requestsToFault)
                { 
                    request.Fault(this); 
                }
            } 
        }

        public override T GetProperty()
        { 
            if (typeof(T) == typeof(IRequestChannel))
            { 
                return (T)(object)this; 
            }
 
            T baseProperty = base.GetProperty();
            if (baseProperty != null)
            {
                return baseProperty; 
            }
 
            return default(T); 
        }
 
        protected override void OnAbort()
        {
            AbortPendingRequests();
        } 

        void ReleaseRequest(IRequestBase request) 
        { 
            lock (outstandingRequests)
            { 
                // Remove supports the connection having been removed, so don't need extra Contains() check,
                // even though this may have been removed by Abort()
                outstandingRequests.Remove(request);
                if (outstandingRequests.Count == 0) 
                {
                    if (!closed && closedEvent != null) 
                    { 
                        closedEvent.Set();
                    } 
                }
            }
        }
 
        void TrackRequest(IRequestBase request)
        { 
            lock (outstandingRequests) 
            {
                ThrowIfDisposedOrNotOpen(); // make sure that we haven't already snapshot our collection 
                outstandingRequests.Add(request);
            }
        }
 
        public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
        { 
            return this.BeginRequest(message, this.DefaultSendTimeout, callback, state); 
        }
 
        public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
        {
            if (message == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); 

            if (timeout < TimeSpan.Zero) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
 
            ThrowIfDisposedOrNotOpen();

            AddHeadersTo(message);
            IAsyncRequest asyncRequest = CreateAsyncRequest(message, callback, state); 
            TrackRequest(asyncRequest);
 
            bool throwing = true; 
            try
            { 
                asyncRequest.BeginSendRequest(message, timeout);
                throwing = false;
            }
            finally 
            {
                if (throwing) 
                { 
                    ReleaseRequest(asyncRequest);
                } 
            }

            return asyncRequest;
        } 

        protected abstract IRequest CreateRequest(Message message); 
        protected abstract IAsyncRequest CreateAsyncRequest(Message message, AsyncCallback callback, object state); 

        public Message EndRequest(IAsyncResult result) 
        {
            if (result == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result"); 
            }
 
            IAsyncRequest asyncRequest = result as IAsyncRequest; 

            if (asyncRequest == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.InvalidAsyncResult));
            }
 
            try
            { 
                Message reply = asyncRequest.End(); 

                if (DiagnosticUtility.ShouldTraceInformation) 
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.RequestChannelReplyReceived, reply);

                return reply;
            } 
            finally
            { 
                ReleaseRequest(asyncRequest); 
            }
        } 

        public Message Request(Message message)
        {
            return this.Request(message, this.DefaultSendTimeout); 
        }
 
        public Message Request(Message message, TimeSpan timeout) 
        {
            if (message == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
            }
 
            if (timeout < TimeSpan.Zero)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 

            ThrowIfDisposedOrNotOpen(); 

            AddHeadersTo(message);
            IRequest request = CreateRequest(message);
            TrackRequest(request); 
            try
            { 
                Message reply; 
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
                TimeSpan savedTimeout = timeoutHelper.RemainingTime();
                try
                {
                    request.SendRequest(message, savedTimeout); 
                }
                catch (TimeoutException timeoutException) 
                { 
                    throw TraceUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.RequestChannelSendTimedOut, savedTimeout),
                        timeoutException), message); 
                }

                savedTimeout = timeoutHelper.RemainingTime();
 
                try
                { 
                    reply = request.WaitForReply(savedTimeout); 
                }
                catch (TimeoutException timeoutException) 
                {
                    throw TraceUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.RequestChannelWaitForReplyTimedOut, savedTimeout),
                        timeoutException), message);
                } 

 
                if (DiagnosticUtility.ShouldTraceInformation) 
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.RequestChannelReplyReceived, reply);
 
                return reply;
            }
            finally
            { 
                ReleaseRequest(request);
            } 
        } 

        protected virtual void AddHeadersTo(Message message) 
        {
            if (!manualAddressing && to != null)
            {
                to.ApplyTo(message); 
            }
        } 
 
        class WaitForPendingRequestsAsyncResult : AsyncResult
        { 
            static WaitOrTimerCallback completeWaitCallBack = new WaitOrTimerCallback(OnCompleteWaitCallBack);
            IRequestBase[] pendingRequests;
            RequestChannel requestChannel;
            TimeSpan timeout; 
            RegisteredWaitHandle waitHandle;
 
            public WaitForPendingRequestsAsyncResult(TimeSpan timeout, RequestChannel requestChannel, IRequestBase[] pendingRequests, AsyncCallback callback, object state) 
                : base(callback, state)
            { 
                this.requestChannel = requestChannel;
                this.pendingRequests = pendingRequests;
                this.timeout = timeout;
 
                if (this.timeout == TimeSpan.Zero || this.pendingRequests == null)
                { 
                    AbortRequests(); 
                    CleanupEvents();
                    Complete(true); 
                }
                else
                {
                    this.waitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject(this.requestChannel.closedEvent, completeWaitCallBack, this, TimeoutHelper.ToMilliseconds(timeout), true); 
                }
            } 
 
            void AbortRequests()
            { 
                if (pendingRequests != null)
                {
                    foreach(IRequestBase request in pendingRequests)
                    { 
                        request.Abort(this.requestChannel);
                    } 
                } 
            }
 
            void CleanupEvents()
            {
                if (requestChannel.closedEvent != null)
                { 
                    if (waitHandle != null)
                    { 
                        waitHandle.Unregister(requestChannel.closedEvent); 
                    }
                    requestChannel.FinishClose(); 
                }
            }

            static void OnCompleteWaitCallBack(object state, bool timedOut) 
            {
                WaitForPendingRequestsAsyncResult thisPtr = (WaitForPendingRequestsAsyncResult)state; 
                Exception completionException = null; 
                try
                { 
                    if (timedOut)
                    {
                        thisPtr.AbortRequests();
                    } 
                    thisPtr.CleanupEvents();
                } 
#pragma warning suppress 56500 // [....], transferring exception to another thread 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                    {
                        throw;
                    } 
                    completionException = e;
                } 
 
                thisPtr.Complete(false, completionException);
            } 

            public static void End(IAsyncResult result)
            {
                AsyncResult.End(result); 
            }
        } 
    } 

    interface IRequestBase 
    {
        void Abort(RequestChannel requestChannel);
        void Fault(RequestChannel requestChannel);
    } 

    interface IRequest : IRequestBase 
    { 
        void SendRequest(Message message, TimeSpan timeout);
        Message WaitForReply(TimeSpan timeout); 
    }

    interface IAsyncRequest : IAsyncResult, IRequestBase
    { 
        void BeginSendRequest(Message message, TimeSpan timeout);
        Message End(); 
    } 
}

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