예제 #1
0
        /// <summary>
        /// Cancels an individual outbound pending request.
        /// </summary>
        /// <param name="state">The ID associated with the request to be canceled.</param>
        private void CancelPendingOutboundRequest(object state)
        {
            Task.Run(async delegate
            {
                try
                {
                    Requires.NotNull(state, nameof(state));
                    object id = state;
                    if (!this.disposed)
                    {
                        var cancellationMessage = JsonRpcMessage.CreateRequestWithNamedParameters(id: null, method: CancelRequestSpecialMethod, namedParameters: new { id = id }, parameterSerializer: DefaultJsonSerializer);
                        await this.TransmitAsync(cancellationMessage, this.disposeCts.Token).ConfigureAwait(false);
                    }
                }
                catch (OperationCanceledException) { }
                catch (ObjectDisposedException) { }
#if DESKTOP
                catch (Exception ex)
                {
                    Debug.Fail(ex.Message, ex.ToString());
                }
#else
                catch (Exception)
                {
                }
#endif
            });
        }
예제 #2
0
        /// <summary>
        /// Invokes the specified RPC method
        /// </summary>
        /// <typeparam name="ReturnType">RPC method return type</typeparam>
        /// <param name="id">An identifier established by the Client that MUST contain a String, Number, or NULL value if included.
        /// If it is not included it is assumed to be a notification.</param>
        /// <param name="targetName">Name of the method to invoke.</param>
        /// <param name="arguments">Arguments to pass to the invoked method. If null, no arguments are passed.</param>
        /// <param name="cancellationToken">The token whose cancellation should signal the server to stop processing this request.</param>
        /// <param name="isParameterObject">Value which indicates if parameter should be passed as an object.</param>
        /// <returns>A task whose result is the deserialized response from the JSON-RPC server.</returns>
        protected virtual async Task <ReturnType> InvokeCoreAsync <ReturnType>(int?id, string targetName, IReadOnlyList <object> arguments, CancellationToken cancellationToken, bool isParameterObject)
        {
            Requires.NotNullOrEmpty(targetName, nameof(targetName));

            Verify.NotDisposed(this);
            cancellationToken.ThrowIfCancellationRequested();

            JsonRpcMessage request;

            if (isParameterObject)
            {
                object argument = arguments;
                if (argument != null)
                {
                    if (arguments.Count != 1 || arguments[0] == null || !arguments[0].GetType().GetTypeInfo().IsClass)
                    {
                        throw new ArgumentException(Resources.ParameterNotObject);
                    }

                    argument = arguments[0];
                }

                request = JsonRpcMessage.CreateRequestWithNamedParameters(id, targetName, argument, this.JsonSerializer);
            }
            else
            {
                arguments = arguments ?? EmptyObjectArray;

                request = JsonRpcMessage.CreateRequest(id, targetName, arguments, this.JsonSerializer);
            }

            using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, this.disposeCts.Token))
            {
                if (id == null)
                {
                    await this.TransmitAsync(request, cts.Token).ConfigureAwait(false);

                    return(default(ReturnType));
                }

                Verify.Operation(this.readLinesTask != null, Resources.InvalidBeforeListenHasStarted);
                var tcs = new TaskCompletionSource <ReturnType>();
                Action <JsonRpcMessage> dispatcher = (response) =>
                {
                    lock (this.dispatcherMapLock)
                    {
                        this.resultDispatcherMap.Remove(id.Value);
                    }

                    try
                    {
                        if (response == null)
                        {
                            tcs.TrySetCanceled();
                        }
                        else if (response.IsError)
                        {
                            tcs.TrySetException(CreateExceptionFromRpcError(response, targetName));
                        }
                        else
                        {
                            tcs.TrySetResult(response.GetResult <ReturnType>(this.JsonSerializer));
                        }
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                };

                var callData = new OutstandingCallData(tcs, dispatcher);
                lock (this.dispatcherMapLock)
                {
                    this.resultDispatcherMap.Add(id.Value, callData);
                }

                await this.TransmitAsync(request, cts.Token).ConfigureAwait(false);

                // Arrange for sending a cancellation message if canceled while we're waiting for a response.
                using (cancellationToken.Register(this.cancelPendingOutboundRequestAction, id.Value, useSynchronizationContext: false))
                {
                    // This task will be completed when the Response object comes back from the other end of the pipe
                    return(await tcs.Task.ConfigureAwait(false));
                }
            }
        }