public virtual IMessageCtrl AsyncProcessMessage(
IMessage msg, IMessageSink replySink)
{
IMethodCallMessage mcMsg = (IMethodCallMessage)msg;
IMessageCtrl retCtrl = null;
IMessage retMessage = null;
LogicalCallContext oldCallCtx = null;
bool isCallContextSet = false;
try{
try
{
LogicalCallContext callCtx = (LogicalCallContext)
mcMsg.Properties[Message.CallContextKey];
Object server = _server;
// validate the method base if necessary
VerifyIsOkToCallMethod(server, mcMsg);
// install call context onto the thread, holding onto
// the one that is currently on the thread
oldCallCtx = CallContext.SetLogicalCallContext(callCtx);
isCallContextSet = true;
// retrieve incoming headers
callCtx.PropagateIncomingHeadersToCallContext(msg);
PreserveThreadPrincipalIfNecessary(callCtx, oldCallCtx);
// see if this is a server message that was dispatched asynchronously
ServerChannelSinkStack sinkStack =
msg.Properties["__SinkStack"] as ServerChannelSinkStack;
if (sinkStack != null)
sinkStack.ServerObject = server;
BCLDebug.Assert((server!=null)==(!_bStatic),
"Invalid state in stackbuilder sink?");
MethodBase mb = GetMethodBase(mcMsg);
Object[] outArgs = null;
Object ret = null;
RemotingMethodCachedData methodCache =
InternalRemotingServices.GetReflectionCachedData(mb);
Object[] args = Message.CoerceArgs(mcMsg, methodCache.Parameters);
ret = PrivateProcessMessage(mb.MethodHandle,
args,
server,
0,
false,
out outArgs);
CopyNonByrefOutArgsFromOriginalArgs(methodCache, args, ref outArgs);
if(replySink != null)
{
// call context could be different then the one from before the call.
LogicalCallContext latestCallContext = CallContext.GetLogicalCallContext();
if (latestCallContext != null)
{
// Special case Principal since if might not be serializable before returning
// ReturnMessage
latestCallContext.RemovePrincipalIfNotSerializable();
}
retMessage = new ReturnMessage(
ret,
outArgs,
(outArgs == null ? 0 : outArgs.Length),
latestCallContext,
mcMsg);
// retrieve outgoing response headers
latestCallContext.PropagateOutgoingHeadersToMessage(retMessage);
}
}
catch (Exception e)
{
if(replySink != null)
{
retMessage = new ReturnMessage(e, mcMsg);
((ReturnMessage)retMessage).SetLogicalCallContext(
(LogicalCallContext)
mcMsg.Properties[Message.CallContextKey]);
}
}
finally
{
// Call the reply sink without catching the exceptions
// in it. In v2.0 any exceptions in the callback for example
// would probably bring down the process
replySink.SyncProcessMessage(retMessage);
}
}
finally {
// restore the call context on the thread
if (isCallContextSet)
CallContext.SetLogicalCallContext(oldCallCtx);
}
return retCtrl;
} // AsyncProcessMessage