async Task <Response> invokeAsync(string name, params object[] args) { if (sendAsync == null) { throw new Exception("The invoker is not initialized."); } var msg = new Request { FunctionName = name, CallId = Guid.NewGuid().ToString(), Arguments = args.Select(a => JToken.FromObject(a, RPC.Serializer)).ToArray() }; var key = msg.FunctionName + "-" + msg.CallId; runningMethods[key] = new RpcWaiter(RequestTerminationDelay); await sendAsync(msg); Response response = default(Response); try { await runningMethods[key].Task; response = runningMethods[key].Task.Result; } //catch (OperationCanceledException) { throw; } finally { runningMethods[key].Dispose(); runningMethods.TryRemove(key, out RpcWaiter _); } return(response); }
//------------------------------------------------------------------------------------------------------------------------ public bool OnMessageReceived(T wrapper_msg, object payload) { //check if this is a response, in which case unblock pending request if (wrapper_msg.IsResponse) { int syncId = wrapper_msg.SyncId; DebugEx.Assert(syncId != 0, "IsResponse flag without valid syncId not allowed"); if (syncId == 0) { return(false); } DebugEx.TraceLog("MsgSync: got " + payload.GetType() + ", syncid: " + wrapper_msg.SyncId); //find waiter RpcWaiter w = null; lock (RpcPending) if (RpcPending.TryGetValue(syncId, out w)) { RpcPending.Remove(syncId); } //remove if found //set result and wake if (w != null) { lock (w) { w.Response = payload; Monitor.Pulse(w); return(true); } } else { DebugEx.TraceError("Could not find MsgSync waiter from " + payload.GetType() + " with syncId=" + syncId); } } return(false); }
//------------------------------------------------------------------------------------------------------------------------ public virtual Trsp SendRequest <Trsp>(T wrapper_msg, object request, TimeSpan?timeout = null, bool auto_json = false) { //null check if (wrapper_msg == null) { DebugEx.Assert("Null wrapper detected"); return(default(Trsp)); } try { //create synchronization id var syncId = GetNewSyncId(); //create waiter var w = new RpcWaiter(); lock (RpcPending) RpcPending.Add(syncId, w); //create wrapper message try { wrapper_msg.IsRequest = true; wrapper_msg.SyncId = syncId; wrapper_msg.Payload = request?.ToJSON(); } catch (Exception ex) { DebugEx.Assert(ex, "msg wrapper create failed"); return(default(Trsp)); } //Send request and wait for response bool failed = false; lock (w) { DebugEx.TraceLog("MsgSync: sending " + request?.GetType() + ", syncid: " + wrapper_msg.SyncId); PublishFunc?.Invoke(wrapper_msg, request); //wait for response #if DEBUG Monitor.Wait(w); #else if (timeout.HasValue) { if (timeout.Value == TimeSpan.Zero) { Monitor.Wait(w); //if explicitly zero timespan, wait forever } else { Monitor.Wait(w, timeout.Value); } } else { //if no value given, wait for default msec Monitor.Wait(w, DefaultRPCTimeout); } #endif if (w.Response == null) { failed = true; } } if (failed) { lock (RpcPending) RpcPending.Remove(syncId); //remove if failed to receive within time limit } //give response back if (w.Response != null) { if (w.Response is string && auto_json) { var rsp_str = w.Response as string; if ((rsp_str.StartsWith("{") && rsp_str.EndsWith("}")) || (rsp_str.StartsWith("[") && rsp_str.EndsWith("]"))) { return((Trsp)rsp_str.FromJSON(type: typeof(Trsp))); } } else { return((Trsp)w.Response); } } return(default(Trsp)); } catch (Exception ex) { DebugEx.TraceErrorException(ex); return(default(Trsp)); } }