Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / 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
- ByteAnimationBase.cs
- ChangeTracker.cs
- BooleanToSelectiveScrollingOrientationConverter.cs
- BatchWriter.cs
- InstanceDescriptor.cs
- SHA512Managed.cs
- ClonableStack.cs
- XmlNodeList.cs
- NotificationContext.cs
- ZipIOLocalFileHeader.cs
- AdCreatedEventArgs.cs
- FlagPanel.cs
- RijndaelManaged.cs
- SystemIPInterfaceStatistics.cs
- ToolStripMenuItem.cs
- ConnectionConsumerAttribute.cs
- CultureTable.cs
- Lease.cs
- EntityUtil.cs
- WebExceptionStatus.cs
- TokenBasedSetEnumerator.cs
- MessagingActivityHelper.cs
- AvTrace.cs
- TemplateColumn.cs
- EntityDataSourceConfigureObjectContextPanel.cs
- Executor.cs
- HtmlContainerControl.cs
- StyleSelector.cs
- AnnotationAdorner.cs
- SpinLock.cs
- TemplatePropertyEntry.cs
- CheckedPointers.cs
- AngleUtil.cs
- AnnotationResourceChangedEventArgs.cs
- ParserOptions.cs
- CodeTypeReferenceExpression.cs
- TypeHelpers.cs
- LineUtil.cs
- CounterCreationDataCollection.cs
- StringReader.cs
- DesigntimeLicenseContextSerializer.cs
- NotSupportedException.cs
- TraceUtils.cs
- SQlBooleanStorage.cs
- ToolStripDropDownItemDesigner.cs
- FutureFactory.cs
- CopyOnWriteList.cs
- MsmqSecureHashAlgorithm.cs
- SerializationAttributes.cs
- InputLanguageProfileNotifySink.cs
- IgnoreSection.cs
- BrowserDefinition.cs
- HashRepartitionStream.cs
- ErrorStyle.cs
- SqlAggregateChecker.cs
- CrossContextChannel.cs
- WebPartConnectionsCloseVerb.cs
- GroupQuery.cs
- DataPointer.cs
- SyndicationPerson.cs
- QilScopedVisitor.cs
- MergeExecutor.cs
- DataGridRowClipboardEventArgs.cs
- DataGridViewCellToolTipTextNeededEventArgs.cs
- KeyBinding.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- Intellisense.cs
- PreservationFileWriter.cs
- PassportAuthentication.cs
- DocumentGridPage.cs
- RawUIStateInputReport.cs
- UserNameSecurityToken.cs
- MapPathBasedVirtualPathProvider.cs
- SimpleMailWebEventProvider.cs
- HwndAppCommandInputProvider.cs
- LogoValidationException.cs
- LabelInfo.cs
- TextElement.cs
- CancellableEnumerable.cs
- InstanceOwner.cs
- WebPartMovingEventArgs.cs
- MaskInputRejectedEventArgs.cs
- DataListItem.cs
- ISCIIEncoding.cs
- HttpFileCollection.cs
- EventDescriptorCollection.cs
- SortQueryOperator.cs
- MsmqInputMessagePool.cs
- LightweightCodeGenerator.cs
- LocationUpdates.cs
- Deflater.cs
- DesignerActionVerbList.cs
- Stack.cs
- _ContextAwareResult.cs
- ZipQueryOperator.cs
- TagNameToTypeMapper.cs
- SpellerInterop.cs
- PropertyMapper.cs
- SystemSounds.cs
- HttpCacheVary.cs