예제 #1
0
        // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but
        // it is reusing fair amount of code in this class, so we are leaving it here.
        /// <summary>
        /// Blocking unary request - unary response call.
        /// </summary>
        public TResponse UnaryCall(TRequest msg)
        {
            var profiler = Profilers.ForCurrentThread();

            using (profiler.NewScope("AsyncCall.UnaryCall"))
                using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.CreateSync())
                {
                    bool callStartedOk = false;
                    try
                    {
                        unaryResponseTcs = new TaskCompletionSource <TResponse>();

                        lock (myLock)
                        {
                            GrpcPreconditions.CheckState(!started);
                            started = true;
                            Initialize(cq);

                            halfcloseRequested = true;
                            readingDone        = true;
                        }

                        byte[] payload = UnsafeSerialize(msg);

                        using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                        {
                            var ctx = details.Channel.Environment.BatchContextPool.Lease();
                            try
                            {
                                call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                                callStartedOk = true;

                                var  ev      = cq.Pluck(ctx.Handle);
                                bool success = (ev.success != 0);
                                try
                                {
                                    using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch"))
                                    {
                                        HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessageReader(), ctx.GetReceivedInitialMetadata());
                                    }
                                }
                                catch (Exception e)
                                {
                                    Logger.Error(e, "Exception occurred while invoking completion delegate.");
                                }
                            }
                            finally
                            {
                                ctx.Recycle();
                            }
                        }
                    }
                    finally
                    {
                        if (!callStartedOk)
                        {
                            lock (myLock)
                            {
                                OnFailedToStartCallLocked();
                            }
                        }
                    }

                    // Once the blocking call returns, the result should be available synchronously.
                    // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException.
                    return(unaryResponseTcs.Task.GetAwaiter().GetResult());
                }
        }
예제 #2
0
        // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but
        // it is reusing fair amount of code in this class, so we are leaving it here.
        /// <summary>
        /// Blocking unary request - unary response call.
        /// </summary>
        public TResponse UnaryCall(TRequest msg)
        {
            var profiler = Profilers.ForCurrentThread();

            using (profiler.NewScope("AsyncCall.UnaryCall"))

                // Create a pluckable completion queue for the call. Avoid creating a completion queue when we know the channel has already
                // been shutdown. In such case, the call will fail with ObjectDisposedException immediately anyway and creating / destroying
                // a completion queue would lead to crash if this was the last channel in the application (and thus GrpcEnvironment has been shutdown).
                // See https://github.com/grpc/grpc/issues/19090
                using (CompletionQueueSafeHandle cq = details.Channel.Handle.IsClosed ?  null : CompletionQueueSafeHandle.CreateSync())
                {
                    bool callStartedOk = false;
                    try
                    {
                        unaryResponseTcs = new TaskCompletionSource <TResponse>();

                        lock (myLock)
                        {
                            GrpcPreconditions.CheckState(!started);
                            started = true;
                            Initialize(cq);

                            halfcloseRequested = true;
                            readingDone        = true;
                        }

                        using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
                            using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                            {
                                var payload = UnsafeSerialize(msg, serializationScope.Context); // do before metadata array?
                                var ctx     = details.Channel.Environment.BatchContextPool.Lease();
                                try
                                {
                                    call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                                    callStartedOk = true;

                                    var  ev      = cq.Pluck(ctx.Handle);
                                    bool success = (ev.success != 0);
                                    try
                                    {
                                        using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch"))
                                        {
                                            HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessageReader(), ctx.GetReceivedInitialMetadata());
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Logger.Error(e, "Exception occurred while invoking completion delegate.");
                                    }
                                }
                                finally
                                {
                                    ctx.Recycle();
                                }
                            }
                    }
                    finally
                    {
                        if (!callStartedOk)
                        {
                            lock (myLock)
                            {
                                OnFailedToStartCallLocked();
                            }
                        }
                    }

                    // Once the blocking call returns, the result should be available synchronously.
                    // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException.
                    return(unaryResponseTcs.Task.GetAwaiter().GetResult());
                }
        }