Пример #1
0
        internal static IMessageCtrl DoAsyncDispatch(IMessage reqMsg, IMessageSink replySink)
        {
            object[]       args           = new object[4];
            ServerIdentity serverIdentity = InternalSink.GetServerIdentity(reqMsg);

            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid id = Guid.Empty;
                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    object obj = reqMsg.Properties[(object)"CORProfilerCookie"];
                    if (obj != null)
                    {
                        id = (Guid)obj;
                    }
                }
                RemotingServices.CORProfilerRemotingServerReceivingMessage(id, true);
                if (replySink != null)
                {
                    replySink = (IMessageSink) new ServerAsyncReplyTerminatorSink(replySink);
                }
            }
            Context serverContext = serverIdentity.ServerContext;

            args[0] = (object)reqMsg;
            args[1] = (object)replySink;
            args[2] = (object)Thread.CurrentContext;
            args[3] = (object)serverContext;
            InternalCrossContextDelegate ftnToCall = new InternalCrossContextDelegate(CrossContextChannel.DoAsyncDispatchCallback);

            return((IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(serverContext, ftnToCall, args));
        }
Пример #2
0
        /// <include file='doc\AsyncResult.uex' path='docs/doc[@for="AsyncResult.SyncProcessMessage"]/*' />
        public virtual IMessage     SyncProcessMessage(IMessage msg)
        {
            if (msg == null)
            {
                _replyMsg = new ReturnMessage(new RemotingException(Environment.GetResourceString("Remoting_NullMessage")), new ErrorMessage());
            }
            else if (!(msg is IMethodReturnMessage))
            {
                _replyMsg = new ReturnMessage(new RemotingException(Environment.GetResourceString("Remoting_Message_BadType")), new ErrorMessage());
            }
            else
            {
                _replyMsg = msg;
            }

            _isCompleted = true;
            FaultInWaitHandle();

            // If profiling, we want to notify the profiler that the remoting code is
            // essentially done (other than returning up the callstack, which happens
            // after the result is saved and/or used so doesn't really count for anything.
            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                RemotingServices.CORProfilerRemotingClientInvocationFinished();
            }

            _AsyncWaitHandle.Set();
            if (_acbd != null)
            {
                // NOTE: We are invoking user code here!
                _acbd(this);
            }
            return(null);
        }
        [System.Security.SecurityCritical]  // auto-generated
        public virtual IMessage SyncProcessMessage(IMessage replyMsg)
        {
            // If this class has been brought into the picture, then the following must be true.
            BCLDebug.Assert(RemotingServices.CORProfilerTrackRemoting(),
                            "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");
            BCLDebug.Assert(RemotingServices.CORProfilerTrackRemotingAsync(),
                            "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");

            Guid g = Guid.Empty;

            // If GUID cookies are active, then we try to get it from the properties dictionary
            if (RemotingServices.CORProfilerTrackRemotingCookie())
            {
                Object obj = replyMsg.Properties["CORProfilerCookie"];

                if (obj != null)
                {
                    g = (Guid)obj;
                }
            }

            // Notify the profiler that we are receiving an async reply from the server-side
            RemotingServices.CORProfilerRemotingClientReceivingReply(g, true);

            // Now that we've done the intercepting, pass the message on to the regular chain
            return(_nextSink.SyncProcessMessage(replyMsg));
        }
Пример #4
0
        [System.Security.SecurityCritical]  // auto-generated
        internal static IMessageCtrl DoAsyncDispatch(IMessage reqMsg, IMessageSink replySink)
        {
            Object[] args = new Object[] { null, null, null, null };

            ServerIdentity srvID = GetServerIdentity(reqMsg);

            // If active, notify the profiler that an asynchronous remoting message was received.
            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid g = Guid.Empty;

                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    Object obj = reqMsg.Properties["CORProfilerCookie"];
                    if (obj != null)
                    {
                        g = (Guid)obj;
                    }
                }

                RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                // Only wrap the replySink if the call wants a reply
                if (replySink != null)
                {
                    // Now wrap the reply sink in our own so that we can notify the profiler of
                    // when the reply is sent.  Upon invocation, it will notify the profiler
                    // then pass control on to the replySink passed in above.
                    IMessageSink profSink =
                        new ServerAsyncReplyTerminatorSink(replySink);

                    // Replace the reply sink with our own
                    replySink = profSink;
                }
            }

            IMessageCtrl msgCtrl = null;
            Context      srvCtx  = srvID.ServerContext;

            //if (srvCtx.IsThreadPoolAware)
            //{
            // this is the case when we do not queue the work item since the
            // server context claims to be doing its own threading.

            args[0] = reqMsg;
            args[1] = replySink;
            args[2] = Thread.CurrentContext;
            args[3] = srvCtx;

            InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(DoAsyncDispatchCallback);

            msgCtrl = (IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(srvCtx, xctxDel, args);

            //}

            return(msgCtrl);
        } // DoDispatch
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            IMessage     message = InternalSink.ValidateMessage(reqMsg);
            IMessageCtrl result  = null;

            if (message == null)
            {
                message = InternalSink.DisallowAsyncActivation(reqMsg);
            }
            if (message != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(message);
                }
            }
            else
            {
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid guid;
                    RemotingServices.CORProfilerRemotingClientSendingMessage(out guid, true);
                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        reqMsg.Properties["CORProfilerCookie"] = guid;
                    }
                    if (replySink != null)
                    {
                        IMessageSink messageSink = new ClientAsyncReplyTerminatorSink(replySink);
                        replySink = messageSink;
                    }
                }
                Context currentContext = Thread.CurrentContext;
                currentContext.NotifyDynamicSinks(reqMsg, true, true, true, true);
                if (replySink != null)
                {
                    replySink = new AsyncReplySink(replySink, currentContext);
                }
                object[] array = new object[3];
                InternalCrossContextDelegate internalCrossContextDelegate = new InternalCrossContextDelegate(ClientContextTerminatorSink.AsyncProcessMessageCallback);
                IMessageSink channelSink = this.GetChannelSink(reqMsg);
                array[0] = reqMsg;
                array[1] = replySink;
                array[2] = channelSink;
                if (channelSink != CrossContextChannel.MessageSink)
                {
                    result = (IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(Context.DefaultContext, internalCrossContextDelegate, array);
                }
                else
                {
                    result = (IMessageCtrl)internalCrossContextDelegate(array);
                }
            }
            return(result);
        }
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            IMessage msg = InternalSink.ValidateMessage(reqMsg);

            object[]     args = new object[4];
            IMessageCtrl ctrl = null;

            if (msg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(msg);
                }
                return(ctrl);
            }
            ServerIdentity serverIdentity = InternalSink.GetServerIdentity(reqMsg);

            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid empty = Guid.Empty;
                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    object obj2 = reqMsg.Properties["CORProfilerCookie"];
                    if (obj2 != null)
                    {
                        empty = (Guid)obj2;
                    }
                }
                RemotingServices.CORProfilerRemotingServerReceivingMessage(empty, true);
                if (replySink != null)
                {
                    IMessageSink sink = new ServerAsyncReplyTerminatorSink(replySink);
                    replySink = sink;
                }
            }
            Context serverContext = serverIdentity.ServerContext;

            if (serverContext.IsThreadPoolAware)
            {
                args[0] = reqMsg;
                args[1] = replySink;
                args[2] = Thread.CurrentContext;
                args[3] = serverContext;
                InternalCrossContextDelegate ftnToCall = new InternalCrossContextDelegate(CrossContextChannel.AsyncProcessMessageCallback);
                return((IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(serverContext, ftnToCall, args));
            }
            AsyncWorkItem item = null;

            item = new AsyncWorkItem(reqMsg, replySink, Thread.CurrentContext, serverIdentity);
            WaitCallback callBack = new WaitCallback(item.FinishAsyncWork);

            ThreadPool.QueueUserWorkItem(callBack);
            return(ctrl);
        }
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            IMessage message = InternalSink.ValidateMessage(reqMsg);

            object[]     array  = new object[4];
            IMessageCtrl result = null;

            if (message != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(message);
                }
            }
            else
            {
                ServerIdentity serverIdentity = InternalSink.GetServerIdentity(reqMsg);
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid id = Guid.Empty;
                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        object obj = reqMsg.Properties["CORProfilerCookie"];
                        if (obj != null)
                        {
                            id = (Guid)obj;
                        }
                    }
                    RemotingServices.CORProfilerRemotingServerReceivingMessage(id, true);
                    if (replySink != null)
                    {
                        IMessageSink messageSink = new ServerAsyncReplyTerminatorSink(replySink);
                        replySink = messageSink;
                    }
                }
                Context serverContext = serverIdentity.ServerContext;
                if (serverContext.IsThreadPoolAware)
                {
                    array[0] = reqMsg;
                    array[1] = replySink;
                    array[2] = Thread.CurrentContext;
                    array[3] = serverContext;
                    InternalCrossContextDelegate ftnToCall = new InternalCrossContextDelegate(CrossContextChannel.AsyncProcessMessageCallback);
                    result = (IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(serverContext, ftnToCall, array);
                }
                else
                {
                    AsyncWorkItem @object  = new AsyncWorkItem(reqMsg, replySink, Thread.CurrentContext, serverIdentity);
                    WaitCallback  callBack = new WaitCallback(@object.FinishAsyncWork);
                    ThreadPool.QueueUserWorkItem(callBack);
                }
            }
            return(result);
        }
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            IMessage     msg  = InternalSink.ValidateMessage(reqMsg);
            IMessageCtrl ctrl = null;

            if (msg == null)
            {
                msg = InternalSink.DisallowAsyncActivation(reqMsg);
            }
            if (msg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(msg);
                }
                return(ctrl);
            }
            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid guid;
                RemotingServices.CORProfilerRemotingClientSendingMessage(out guid, true);
                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    reqMsg.Properties["CORProfilerCookie"] = guid;
                }
                if (replySink != null)
                {
                    IMessageSink sink = new ClientAsyncReplyTerminatorSink(replySink);
                    replySink = sink;
                }
            }
            Context currentContext = Thread.CurrentContext;

            currentContext.NotifyDynamicSinks(reqMsg, true, true, true, true);
            if (replySink != null)
            {
                replySink = new System.Runtime.Remoting.Messaging.AsyncReplySink(replySink, currentContext);
            }
            object[] args = new object[3];
            InternalCrossContextDelegate ftnToCall = new InternalCrossContextDelegate(ClientContextTerminatorSink.AsyncProcessMessageCallback);
            IMessageSink channelSink = this.GetChannelSink(reqMsg);

            args[0] = reqMsg;
            args[1] = replySink;
            args[2] = channelSink;
            if (channelSink != CrossContextChannel.MessageSink)
            {
                return((IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(Context.DefaultContext, ftnToCall, args));
            }
            return((IMessageCtrl)ftnToCall(args));
        }
Пример #9
0
        public virtual IMessage SyncProcessMessage(IMessage replyMsg)
        {
            // If this class has been brought into the picture, then the following must be true.
            BCLDebug.Assert(RemotingServices.CORProfilerTrackRemoting(),
                            "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");
            BCLDebug.Assert(RemotingServices.CORProfilerTrackRemotingAsync(),
                            "CORProfilerTrackRemoting returned false, but we're in AsyncProcessMessage!");

            Guid g;

            // Notify the profiler that we are receiving an async reply from the server-side
            RemotingServices.CORProfilerRemotingServerSendingReply(out g, true);

            // If GUID cookies are active, then we save it for the other end of the channel
            if (RemotingServices.CORProfilerTrackRemotingCookie())
            {
                replyMsg.Properties["CORProfilerCookie"] = g;
            }

            // Now that we've done the intercepting, pass the message on to the regular chain
            return(_nextSink.SyncProcessMessage(replyMsg));
        }
Пример #10
0
        [System.Security.SecurityCritical]  // auto-generated
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call starting!!\n");
            // One way Async notifications may potentially pass a null reply sink.
            IMessage errMsg = ValidateMessage(reqMsg);

            Object[] args = new Object[] { null, null, null, null };

            IMessageCtrl msgCtrl = null;

            if (errMsg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(errMsg);
                }
            }
            else
            {
                ServerIdentity srvID = GetServerIdentity(reqMsg);

                // If active, notify the profiler that an asynchronous remoting message was received.
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid g = Guid.Empty;

                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        Object obj = reqMsg.Properties["CORProfilerCookie"];

                        if (obj != null)
                        {
                            g = (Guid)obj;
                        }
                    }

                    RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                    // Only wrap the replySink if the call wants a reply
                    if (replySink != null)
                    {
                        // Now wrap the reply sink in our own so that we can notify the profiler of
                        // when the reply is sent.  Upon invocation, it will notify the profiler
                        // then pass control on to the replySink passed in above.
                        IMessageSink profSink = new ServerAsyncReplyTerminatorSink(replySink);

                        // Replace the reply sink with our own
                        replySink = profSink;
                    }
                }

                Context srvCtx = srvID.ServerContext;
                if (srvCtx.IsThreadPoolAware)
                {
                    // this is the case when we do not queue the work item since the
                    // server context claims to be doing its own threading.

                    args[0] = reqMsg;
                    args[1] = replySink;
                    args[2] = Thread.CurrentContext;
                    args[3] = srvCtx;

                    InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(AsyncProcessMessageCallback);

                    msgCtrl = (IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(srvCtx, xctxDel, args);
                }
                else
                {
                    AsyncWorkItem workItem = null;

                    // This is the case where we take care of returning the calling
                    // thread asap by using the ThreadPool for completing the call.

                    // we use a more elaborate WorkItem and delegate the work to the thread pool
                    workItem = new AsyncWorkItem(reqMsg,
                                                 replySink,
                                                 Thread.CurrentContext,
                                                 srvID);

                    WaitCallback threadFunc = new WaitCallback(workItem.FinishAsyncWork);
                    // Note: Dynamic sinks are notified in the threadFunc
                    ThreadPool.QueueUserWorkItem(threadFunc);
                }
            }

            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call returning!!\n");
            return(msgCtrl);
        } // AsyncProcessMessage
Пример #11
0
        } // AsyncProcessMessage

        internal static IMessageCtrl DoAsyncDispatch(IMessage reqMsg, IMessageSink replySink)
        {
            ServerIdentity srvID    = GetServerIdentity(reqMsg);
            AsyncWorkItem  workItem = null;

            // If active, notify the profiler that an asynchronous remoting message was received.
            if (RemotingServices.CORProfilerTrackRemotingAsync())
            {
                Guid g = Guid.Empty;

                if (RemotingServices.CORProfilerTrackRemotingCookie())
                {
                    Object obj = reqMsg.Properties["CORProfilerCookie"];
                    if (obj != null)
                    {
                        g = (Guid)obj;
                    }
                }

                RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                // Only wrap the replySink if the call wants a reply
                if (replySink != null)
                {
                    // Now wrap the reply sink in our own so that we can notify the profiler of
                    // when the reply is sent.  Upon invocation, it will notify the profiler
                    // then pass control on to the replySink passed in above.
                    IMessageSink profSink =
                        new ServerAsyncReplyTerminatorSink(replySink);

                    // Replace the reply sink with our own
                    replySink = profSink;
                }
            }

            Context srvCtx = srvID.ServerContext;

            //if (srvCtx.IsThreadPoolAware)
            //{
            // this is the case when we do not queue the work item since the
            // server context claims to be doing its own threading.

            Context oldCtx = Thread.CurrentContext;
            // change to server object context
            ContextTransitionFrame frame = new ContextTransitionFrame();

            Thread.CurrentThread.EnterContext(srvID.ServerContext, ref frame);

            // we use the work item just as our replySink in this case
            if (replySink != null)
            {
                workItem = new AsyncWorkItem(replySink, oldCtx);
            }
            Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain");
            // call the server context chain
            IMessageCtrl msgCtrl =
                srvID.ServerContext.GetServerContextChain().AsyncProcessMessage(reqMsg, (IMessageSink)workItem);

            Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain");
            // chain back to the dispatch thread context
            Thread.CurrentThread.ReturnToContext(ref frame);

            //}

            return(msgCtrl);
        } // DoDispatch
Пример #12
0
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call starting!!\n");
            // One way Async notifications may potentially pass a null reply sink.
            IMessage     errMsg  = ValidateMessage(reqMsg);
            IMessageCtrl msgCtrl = null;

            if (errMsg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(errMsg);
                }
            }
            else
            {
                ServerIdentity srvID    = GetServerIdentity(reqMsg);
                AsyncWorkItem  workItem = null;

                // If active, notify the profiler that an asynchronous remoting message was received.
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid g = Guid.Empty;

                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        Object obj = reqMsg.Properties["CORProfilerCookie"];

                        if (obj != null)
                        {
                            g = (Guid)obj;
                        }
                    }

                    RemotingServices.CORProfilerRemotingServerReceivingMessage(g, true);

                    // Only wrap the replySink if the call wants a reply
                    if (replySink != null)
                    {
                        // Now wrap the reply sink in our own so that we can notify the profiler of
                        // when the reply is sent.  Upon invocation, it will notify the profiler
                        // then pass control on to the replySink passed in above.
                        IMessageSink profSink = new ServerAsyncReplyTerminatorSink(replySink);

                        // Replace the reply sink with our own
                        replySink = profSink;
                    }
                }

                Context srvCtx = srvID.ServerContext;
                if (srvCtx.IsThreadPoolAware)
                {
                    // this is the case when we do not queue the work item since the
                    // server context claims to be doing its own threading.

                    Context oldCtx = Thread.CurrentContext;
                    // change to server object context
                    ContextTransitionFrame frame = new ContextTransitionFrame();
                    srvCtx = srvID.ServerContext;
                    Thread.CurrentThread.EnterContext(srvCtx, ref frame);

                    // we use the work item just as our replySink in this case
                    if (replySink != null)
                    {
                        workItem = new AsyncWorkItem(replySink, oldCtx);
                    }

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain");

                    srvCtx.NotifyDynamicSinks(
                        reqMsg,
                        false,          // bCliSide
                        true,           // bStart
                        true,           // bAsync
                        true);          // bNotifyGlobals

                    // call the server context chain
                    msgCtrl =
                        srvCtx.GetServerContextChain().AsyncProcessMessage(
                            reqMsg,
                            (IMessageSink)workItem);

                    // Note: for async calls, we will do the return notification
                    // for dynamic properties only when the async call
                    // completes (i.e. when the replySink gets called)

                    Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain");

                    // chain back to the dispatch thread context
                    Thread.CurrentThread.ReturnToContext(ref frame);
                }
                else
                {
                    // This is the case where we take care of returning the calling
                    // thread asap by using the ThreadPool for completing the call.

                    // we use a more elaborate WorkItem and delegate the work to the thread pool
                    workItem = new AsyncWorkItem(reqMsg,
                                                 replySink,
                                                 Thread.CurrentContext,
                                                 srvID);

                    WaitCallback threadFunc = new WaitCallback(workItem.FinishAsyncWork);
                    // Note: Dynamic sinks are notified in the threadFunc
                    ThreadPool.QueueUserWorkItem(threadFunc);

                    msgCtrl = null;
                }
            }

            Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: Async call returning!!\n");
            return(msgCtrl);
        } // AsyncProcessMessage
        [System.Security.SecurityCritical]  // auto-generated
        public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
        {
            Message.DebugOut("+++++++++++++++++++++++++ CliCtxTerminator: AsyncProcessMsg");
            IMessage     errMsg  = ValidateMessage(reqMsg);
            IMessageCtrl msgCtrl = null;

            if (errMsg == null)
            {
                errMsg = DisallowAsyncActivation(reqMsg);
            }

            if (errMsg != null)
            {
                if (replySink != null)
                {
                    replySink.SyncProcessMessage(errMsg);
                }
            }
            else
            {
                // If active, notify the profiler that an asynchronous remoting call is being made.
                if (RemotingServices.CORProfilerTrackRemotingAsync())
                {
                    Guid g;

                    RemotingServices.CORProfilerRemotingClientSendingMessage(out g, true);

                    if (RemotingServices.CORProfilerTrackRemotingCookie())
                    {
                        reqMsg.Properties["CORProfilerCookie"] = g;
                    }

                    // Only wrap the replySink if the call wants a reply
                    if (replySink != null)
                    {
                        // Now wrap the reply sink in our own so that we can notify the profiler of
                        // when the reply is received.  Upon invocation, it will notify the profiler
                        // then pass control on to the replySink passed in above.
                        IMessageSink profSink = new ClientAsyncReplyTerminatorSink(replySink);

                        // Replace the reply sink with our own
                        replySink = profSink;
                    }
                }

                Context cliCtx = Thread.CurrentContext;

                // Notify dynamic sinks that an Async call started
                cliCtx.NotifyDynamicSinks(
                    reqMsg,
                    true,       // bCliSide
                    true,       // bStart
                    true,       // bAsync
                    true);      // bNotifyGlobals

                // Intercept the async reply to force the thread back
                // into the client-context before it executes further
                // and to notify dynamic sinks
                if (replySink != null)
                {
                    replySink = new AsyncReplySink(replySink, cliCtx);
                }

                Object[] args = new Object[] { null, null, null };
                InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(AsyncProcessMessageCallback);

                IMessageSink channelSink = GetChannelSink(reqMsg);

                // Forward call to the channel.
                args[0] = reqMsg;
                args[1] = replySink;
                args[2] = channelSink;

                // Move to default context unless we are going through
                // the cross-context channel
                if (channelSink != CrossContextChannel.MessageSink)
                {
                    msgCtrl = (IMessageCtrl)Thread.CurrentThread.InternalCrossContextCallback(Context.DefaultContext, xctxDel, args);
                }
                else
                {
                    msgCtrl = (IMessageCtrl)xctxDel(args);
                }
            }
            return(msgCtrl);
        }