Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / clr / src / BCL / System / Runtime / Remoting / CrossContextChannel.cs / 1 / CrossContextChannel.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // Remoting Infrastructure Sink for making calls across context // boundaries. // namespace System.Runtime.Remoting.Channels { using System; using System.Collections; using System.Threading; using System.Runtime.Remoting; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Messaging; using System.Runtime.Serialization; /* package scope */ // deliberately not [serializable] internal class CrossContextChannel : InternalSink, IMessageSink { private const String _channelName = "XCTX"; private const int _channelCapability = 0; private const String _channelURI = "XCTX_URI"; private static CrossContextChannel messageSink { get { return Thread.GetDomain().RemotingData.ChannelServicesData.xctxmessageSink; } set { Thread.GetDomain().RemotingData.ChannelServicesData.xctxmessageSink = value; } } private static Object staticSyncObject = new Object(); private static InternalCrossContextDelegate s_xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); internal static IMessageSink MessageSink { get { if (messageSink == null) { CrossContextChannel tmpSink = new CrossContextChannel(); lock (staticSyncObject) { if (messageSink == null) { messageSink = tmpSink; } } //Interlocked.CompareExchange(out messageSink, tmpSink, null); } return messageSink; } } internal static Object SyncProcessMessageCallback(Object[] args) { IMessage reqMsg = args[0] as IMessage; Context srvCtx = args[1] as Context; IMessage replyMsg = null; // If profiling of remoting is active, must tell the profiler that we have received // a message. if (RemotingServices.CORProfilerTrackRemoting()) { Guid g = Guid.Empty; if (RemotingServices.CORProfilerTrackRemotingCookie()) { Object obj = reqMsg.Properties["CORProfilerCookie"]; if (obj != null) { g = (Guid) obj; } } RemotingServices.CORProfilerRemotingServerReceivingMessage(g, false); } Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain"); // Server side notifications for dynamic sinks are done // in the x-context channel ... this is to maintain // symmetry of the point of notification between // the client and server context srvCtx.NotifyDynamicSinks( reqMsg, false, // bCliSide true, // bStart false, // bAsync true); // bNotifyGlobals replyMsg = srvCtx.GetServerContextChain().SyncProcessMessage(reqMsg); srvCtx.NotifyDynamicSinks( replyMsg, false, // bCliSide false, // bStart false, // bAsync true); // bNotifyGlobals Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain"); // If profiling of remoting is active, must tell the profiler that we are sending a // reply message. if (RemotingServices.CORProfilerTrackRemoting()) { Guid g; RemotingServices.CORProfilerRemotingServerSendingReply(out g, false); if (RemotingServices.CORProfilerTrackRemotingCookie()) { replyMsg.Properties["CORProfilerCookie"] = g; } } return replyMsg; } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Object[] args = new Object[] { null, null }; IMessage replyMsg = null; try { Message.DebugOut("\n::::::::::::::::::::::::: CrossContext Channel: [....] call starting"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } ServerIdentity srvID = GetServerIdentity(reqMsg); Message.DebugOut("Got Server identity \n"); BCLDebug.Assert(null != srvID,"null != srvID"); BCLDebug.Assert(null != srvID.ServerContext, "null != srvID.ServerContext"); args[0] = reqMsg; args[1] = srvID.ServerContext; replyMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(srvID.ServerContext, s_xctxDel, args); } catch(Exception e) { Message.DebugOut("Arrgh.. XCTXSink::throwing exception " + e + "\n"); replyMsg = new ReturnMessage(e, (IMethodCallMessage)reqMsg); if (reqMsg!=null) { ((ReturnMessage)replyMsg).SetLogicalCallContext( (LogicalCallContext) reqMsg.Properties[Message.CallContextKey]); } } Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: [....] call returning!!\n"); return replyMsg; } internal static Object AsyncProcessMessageCallback(Object[] args) { AsyncWorkItem workItem = null; IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; Context oldCtx = (Context) args[2]; Context srvCtx = (Context) args[3]; IMessageCtrl msgCtrl = null; // 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"); return msgCtrl; } 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 internal static Object DoAsyncDispatchCallback(Object[] args) { AsyncWorkItem workItem = null; IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; Context oldCtx = (Context) args[2]; Context srvCtx = (Context) args[3]; IMessageCtrl msgCtrl = null; // 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 msgCtrl = srvCtx.GetServerContextChain().AsyncProcessMessage(reqMsg, (IMessageSink)workItem); Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain"); return msgCtrl; } 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 IMessageSink NextSink { get { // We are a terminating sink for this chain. return null; } } } /* package */ internal class AsyncWorkItem : IMessageSink { // the replySink passed in to us in AsyncProcessMsg private IMessageSink _replySink; // the server identity we are calling private ServerIdentity _srvID; // the original context of the thread calling AsyncProcessMsg private Context _oldCtx; private LogicalCallContext _callCtx; // the request msg passed in private IMessage _reqMsg; internal AsyncWorkItem(IMessageSink replySink, Context oldCtx) : this(null, replySink, oldCtx, null) { } internal AsyncWorkItem(IMessage reqMsg, IMessageSink replySink, Context oldCtx, ServerIdentity srvID) { _reqMsg = reqMsg; _replySink = replySink; _oldCtx = oldCtx; _callCtx = CallContext.GetLogicalCallContext(); _srvID = srvID; } internal static Object SyncProcessMessageCallback(Object[] args) { IMessageSink replySink = (IMessageSink) args[0]; IMessage msg = (IMessage) args[1]; return replySink.SyncProcessMessage(msg); } public virtual IMessage SyncProcessMessage(IMessage msg) { // This gets called when the called object finishes the AsyncWork... // This is called irrespective of whether we delegated the initial // work to a thread pool thread or not. Quite likely it will be // called on a user thread (i.e. a thread different from the // forward call thread) // we just switch back to the old context before calling // the next replySink IMessage retMsg = null; if (_replySink != null) { // This assert covers the common case (ThreadPool) // and checks that the reply thread for the async call // indeed emerges from the server context. BCLDebug.Assert( (_srvID == null) || (_srvID.ServerContext == Thread.CurrentContext), "Thread expected to be in the server context!"); // Call the dynamic sinks to notify that the async call // has completed Thread.CurrentContext.NotifyDynamicSinks( msg, // this is the async reply false, // bCliSide false, // bStart true, // bAsync true); // bNotifyGlobals Object[] args = new Object[] { _replySink, msg }; InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); retMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(_oldCtx, xctxDel, args); } return retMsg; } public virtual IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { // Can't call the reply sink asynchronously! throw new NotSupportedException( Environment.GetResourceString("NotSupported_Method")); } public IMessageSink NextSink { get { return _replySink; } } internal static Object FinishAsyncWorkCallback(Object[] args) { AsyncWorkItem This = (AsyncWorkItem) args[0]; Context srvCtx = This._srvID.ServerContext; LogicalCallContext threadPoolCallCtx = CallContext.SetLogicalCallContext(This._callCtx); // Call the server context chain Async. We provide workItem as our // replySink ... this will cause the replySink.ProcessMessage // to switch back to the context of the original caller thread. // Call the dynamic sinks to notify that the async call // is starting srvCtx.NotifyDynamicSinks( This._reqMsg, false, // bCliSide true, // bStart true, // bAsync true); // bNotifyGlobals // < IMessageCtrl ctrl = srvCtx.GetServerContextChain().AsyncProcessMessage( This._reqMsg, (IMessageSink)This); // change back to the old context CallContext.SetLogicalCallContext(threadPoolCallCtx); return null; } /* package */ internal virtual void FinishAsyncWork(Object stateIgnored) { InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(FinishAsyncWorkCallback); Object[] args = new Object[] { this }; Thread.CurrentThread.InternalCrossContextCallback(_srvID.ServerContext, xctxDel, args); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // Remoting Infrastructure Sink for making calls across context // boundaries. // namespace System.Runtime.Remoting.Channels { using System; using System.Collections; using System.Threading; using System.Runtime.Remoting; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Messaging; using System.Runtime.Serialization; /* package scope */ // deliberately not [serializable] internal class CrossContextChannel : InternalSink, IMessageSink { private const String _channelName = "XCTX"; private const int _channelCapability = 0; private const String _channelURI = "XCTX_URI"; private static CrossContextChannel messageSink { get { return Thread.GetDomain().RemotingData.ChannelServicesData.xctxmessageSink; } set { Thread.GetDomain().RemotingData.ChannelServicesData.xctxmessageSink = value; } } private static Object staticSyncObject = new Object(); private static InternalCrossContextDelegate s_xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); internal static IMessageSink MessageSink { get { if (messageSink == null) { CrossContextChannel tmpSink = new CrossContextChannel(); lock (staticSyncObject) { if (messageSink == null) { messageSink = tmpSink; } } //Interlocked.CompareExchange(out messageSink, tmpSink, null); } return messageSink; } } internal static Object SyncProcessMessageCallback(Object[] args) { IMessage reqMsg = args[0] as IMessage; Context srvCtx = args[1] as Context; IMessage replyMsg = null; // If profiling of remoting is active, must tell the profiler that we have received // a message. if (RemotingServices.CORProfilerTrackRemoting()) { Guid g = Guid.Empty; if (RemotingServices.CORProfilerTrackRemotingCookie()) { Object obj = reqMsg.Properties["CORProfilerCookie"]; if (obj != null) { g = (Guid) obj; } } RemotingServices.CORProfilerRemotingServerReceivingMessage(g, false); } Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: passing to ServerContextChain"); // Server side notifications for dynamic sinks are done // in the x-context channel ... this is to maintain // symmetry of the point of notification between // the client and server context srvCtx.NotifyDynamicSinks( reqMsg, false, // bCliSide true, // bStart false, // bAsync true); // bNotifyGlobals replyMsg = srvCtx.GetServerContextChain().SyncProcessMessage(reqMsg); srvCtx.NotifyDynamicSinks( replyMsg, false, // bCliSide false, // bStart false, // bAsync true); // bNotifyGlobals Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain"); // If profiling of remoting is active, must tell the profiler that we are sending a // reply message. if (RemotingServices.CORProfilerTrackRemoting()) { Guid g; RemotingServices.CORProfilerRemotingServerSendingReply(out g, false); if (RemotingServices.CORProfilerTrackRemotingCookie()) { replyMsg.Properties["CORProfilerCookie"] = g; } } return replyMsg; } public virtual IMessage SyncProcessMessage(IMessage reqMsg) { Object[] args = new Object[] { null, null }; IMessage replyMsg = null; try { Message.DebugOut("\n::::::::::::::::::::::::: CrossContext Channel: [....] call starting"); IMessage errMsg = ValidateMessage(reqMsg); if (errMsg != null) { return errMsg; } ServerIdentity srvID = GetServerIdentity(reqMsg); Message.DebugOut("Got Server identity \n"); BCLDebug.Assert(null != srvID,"null != srvID"); BCLDebug.Assert(null != srvID.ServerContext, "null != srvID.ServerContext"); args[0] = reqMsg; args[1] = srvID.ServerContext; replyMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(srvID.ServerContext, s_xctxDel, args); } catch(Exception e) { Message.DebugOut("Arrgh.. XCTXSink::throwing exception " + e + "\n"); replyMsg = new ReturnMessage(e, (IMethodCallMessage)reqMsg); if (reqMsg!=null) { ((ReturnMessage)replyMsg).SetLogicalCallContext( (LogicalCallContext) reqMsg.Properties[Message.CallContextKey]); } } Message.DebugOut("::::::::::::::::::::::::::: CrossContext Channel: [....] call returning!!\n"); return replyMsg; } internal static Object AsyncProcessMessageCallback(Object[] args) { AsyncWorkItem workItem = null; IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; Context oldCtx = (Context) args[2]; Context srvCtx = (Context) args[3]; IMessageCtrl msgCtrl = null; // 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"); return msgCtrl; } 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 internal static Object DoAsyncDispatchCallback(Object[] args) { AsyncWorkItem workItem = null; IMessage reqMsg = (IMessage) args[0]; IMessageSink replySink = (IMessageSink) args[1]; Context oldCtx = (Context) args[2]; Context srvCtx = (Context) args[3]; IMessageCtrl msgCtrl = null; // 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 msgCtrl = srvCtx.GetServerContextChain().AsyncProcessMessage(reqMsg, (IMessageSink)workItem); Message.DebugOut("::::::::::::::::::::::::: CrossContext Channel: back from ServerContextChain"); return msgCtrl; } 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 IMessageSink NextSink { get { // We are a terminating sink for this chain. return null; } } } /* package */ internal class AsyncWorkItem : IMessageSink { // the replySink passed in to us in AsyncProcessMsg private IMessageSink _replySink; // the server identity we are calling private ServerIdentity _srvID; // the original context of the thread calling AsyncProcessMsg private Context _oldCtx; private LogicalCallContext _callCtx; // the request msg passed in private IMessage _reqMsg; internal AsyncWorkItem(IMessageSink replySink, Context oldCtx) : this(null, replySink, oldCtx, null) { } internal AsyncWorkItem(IMessage reqMsg, IMessageSink replySink, Context oldCtx, ServerIdentity srvID) { _reqMsg = reqMsg; _replySink = replySink; _oldCtx = oldCtx; _callCtx = CallContext.GetLogicalCallContext(); _srvID = srvID; } internal static Object SyncProcessMessageCallback(Object[] args) { IMessageSink replySink = (IMessageSink) args[0]; IMessage msg = (IMessage) args[1]; return replySink.SyncProcessMessage(msg); } public virtual IMessage SyncProcessMessage(IMessage msg) { // This gets called when the called object finishes the AsyncWork... // This is called irrespective of whether we delegated the initial // work to a thread pool thread or not. Quite likely it will be // called on a user thread (i.e. a thread different from the // forward call thread) // we just switch back to the old context before calling // the next replySink IMessage retMsg = null; if (_replySink != null) { // This assert covers the common case (ThreadPool) // and checks that the reply thread for the async call // indeed emerges from the server context. BCLDebug.Assert( (_srvID == null) || (_srvID.ServerContext == Thread.CurrentContext), "Thread expected to be in the server context!"); // Call the dynamic sinks to notify that the async call // has completed Thread.CurrentContext.NotifyDynamicSinks( msg, // this is the async reply false, // bCliSide false, // bStart true, // bAsync true); // bNotifyGlobals Object[] args = new Object[] { _replySink, msg }; InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(SyncProcessMessageCallback); retMsg = (IMessage) Thread.CurrentThread.InternalCrossContextCallback(_oldCtx, xctxDel, args); } return retMsg; } public virtual IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { // Can't call the reply sink asynchronously! throw new NotSupportedException( Environment.GetResourceString("NotSupported_Method")); } public IMessageSink NextSink { get { return _replySink; } } internal static Object FinishAsyncWorkCallback(Object[] args) { AsyncWorkItem This = (AsyncWorkItem) args[0]; Context srvCtx = This._srvID.ServerContext; LogicalCallContext threadPoolCallCtx = CallContext.SetLogicalCallContext(This._callCtx); // Call the server context chain Async. We provide workItem as our // replySink ... this will cause the replySink.ProcessMessage // to switch back to the context of the original caller thread. // Call the dynamic sinks to notify that the async call // is starting srvCtx.NotifyDynamicSinks( This._reqMsg, false, // bCliSide true, // bStart true, // bAsync true); // bNotifyGlobals // < IMessageCtrl ctrl = srvCtx.GetServerContextChain().AsyncProcessMessage( This._reqMsg, (IMessageSink)This); // change back to the old context CallContext.SetLogicalCallContext(threadPoolCallCtx); return null; } /* package */ internal virtual void FinishAsyncWork(Object stateIgnored) { InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(FinishAsyncWorkCallback); Object[] args = new Object[] { this }; Thread.CurrentThread.InternalCrossContextCallback(_srvID.ServerContext, xctxDel, args); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ViewLoader.cs
- TableLayoutStyle.cs
- ClientType.cs
- returneventsaver.cs
- Literal.cs
- versioninfo.cs
- DocumentViewerBaseAutomationPeer.cs
- TextServicesProperty.cs
- RegexMatch.cs
- CngUIPolicy.cs
- TemplatedAdorner.cs
- ComplexPropertyEntry.cs
- SimpleBitVector32.cs
- ValueSerializer.cs
- HttpCapabilitiesSectionHandler.cs
- SecurityState.cs
- Form.cs
- ListViewGroup.cs
- CheckedPointers.cs
- BypassElementCollection.cs
- BaseProcessor.cs
- MsmqHostedTransportConfiguration.cs
- activationcontext.cs
- DetailsViewDeletedEventArgs.cs
- FatalException.cs
- DrawingContextDrawingContextWalker.cs
- DataGridTextBoxColumn.cs
- OleDbException.cs
- XmlSchemaAttributeGroupRef.cs
- SchemaElement.cs
- OleDbTransaction.cs
- XmlSchemaProviderAttribute.cs
- AudioFormatConverter.cs
- XmlKeywords.cs
- HttpFileCollection.cs
- PathSegmentCollection.cs
- HScrollProperties.cs
- DataControlImageButton.cs
- SiteMapPath.cs
- PageBreakRecord.cs
- RegistrationServices.cs
- AsnEncodedData.cs
- StickyNoteContentControl.cs
- LayoutUtils.cs
- TargetControlTypeCache.cs
- IndentTextWriter.cs
- ScriptingAuthenticationServiceSection.cs
- CodeCatchClauseCollection.cs
- SafeViewOfFileHandle.cs
- NumericUpDownAccelerationCollection.cs
- FormatConvertedBitmap.cs
- StandardTransformFactory.cs
- ConfigurationValidatorAttribute.cs
- DateRangeEvent.cs
- Authorization.cs
- QueryTaskGroupState.cs
- SqlLiftWhereClauses.cs
- PointLightBase.cs
- ObjectView.cs
- SwitchDesigner.xaml.cs
- ServiceModelConfigurationSection.cs
- UniqueConstraint.cs
- SynchronizationContext.cs
- DbParameterCollectionHelper.cs
- BindingGroup.cs
- MemoryStream.cs
- StringToken.cs
- GridViewCommandEventArgs.cs
- PathSegment.cs
- BitmapCodecInfo.cs
- SplitterCancelEvent.cs
- ChangeConflicts.cs
- XmlCodeExporter.cs
- ScrollProperties.cs
- PageThemeParser.cs
- RemotingAttributes.cs
- InputProviderSite.cs
- SqlBuffer.cs
- XmlWellformedWriter.cs
- httpapplicationstate.cs
- StorageScalarPropertyMapping.cs
- PerformanceCountersBase.cs
- InternalBufferOverflowException.cs
- SecurityElement.cs
- UserNameSecurityTokenParameters.cs
- ValueUtilsSmi.cs
- clipboard.cs
- WSSecurityOneDotOneReceiveSecurityHeader.cs
- Rfc2898DeriveBytes.cs
- PropertyDescriptorGridEntry.cs
- XmlDataSourceNodeDescriptor.cs
- ListViewSortEventArgs.cs
- FtpRequestCacheValidator.cs
- TemplateField.cs
- FixUpCollection.cs
- HtmlEncodedRawTextWriter.cs
- _SSPISessionCache.cs
- SecurityPermission.cs
- BinaryMethodMessage.cs
- DataException.cs