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