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);
        }
Example #2
0
        //------------------------------------------------------------------------------------------------------------------------
        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);
        }
Example #3
0
        //------------------------------------------------------------------------------------------------------------------------
        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));
            }
        }