/**
* This is how you invoke a method on a remote host.
* Results are put into the Channel.
*
* If you want to have an Event based approach, listen to the EnqueueEvent
* on the Channel you pass for the results. That will be fired
* immediately from the thread that gets the result.
*
* When a result comes back, we put and RpcResult into the Channel.
* When you have enough responses, Close the queue (please). The code
* will stop sending requests after the queue is closed. If you never close
* the queue, this will be wasteful of resources.
*
* @param target the sender to use when making the RPC call
* @param q the Channel into which the RpcResult objects will be placed.
* q may be null if you don't care about the response.
* @param method the Rpc method to call
*
* @throw Exception if we cannot send the request for some reason.
*/
virtual public void Invoke(ISender target, Channel q, string method,
params object[] args)
{
//build state for the RPC call
RpcRequestState rs = new RpcRequestState();
rs.Results = q;
rs.RpcTarget = target;
object[] rpc_call = new object[2];
rpc_call[0] = method;
if (args != null)
{
rpc_call[1] = args;
}
else
{
//There are no args, which we represent as a zero length list
rpc_call[1] = new object[0];
}
AdrCopyable req_copy = new AdrCopyable(rpc_call);
#if RPC_DEBUG
Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}",
_rrman.Info, method, target);
#endif
ICopyable rrpayload = new CopyList(PType.Protocol.Rpc, req_copy);
int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request,
rrpayload, this, rs);
//Make sure we stop this request when the queue is closed.
if (q != null)
{
try {
q.CloseEvent += delegate(object qu, EventArgs eargs) {
_rrman.StopRequest(reqid, this);
};
}
catch {
if (q.Closed)
{
_rrman.StopRequest(reqid, this);
}
else
{
throw;
}
}
}
}