Пример #1
0
        public ValueTask <Task <IncomingResponseFrame>?> SendRequestAsync(
            OutgoingRequestFrame outgoingRequestFrame,
            bool oneway,
            bool synchronous,
            IInvocationObserver?observer,
            CancellationToken cancel)
        {
            cancel.ThrowIfCancellationRequested();

            //
            // Increase the direct count to prevent the thread pool from being destroyed before
            // invokeAll is called. This will also throw if the object adapter has been deactivated.
            //
            _adapter.IncDirectCount();

            IChildInvocationObserver?childObserver = null;
            int requestId = 0;

            // The CollocatedRequestHandler is an internal object so it's safe to lock (this) as long as our
            // code doesn't use the collocated request handler as a lock. The lock here is useful to ensure
            // the protocol trace and observer call is output or called in the same order as the request ID
            // is allocated.
            lock (_mutex)
            {
                if (!oneway)
                {
                    requestId = ++_requestId;
                }

                if (observer != null)
                {
                    childObserver = observer.GetCollocatedObserver(_adapter, requestId, outgoingRequestFrame.Size);
                    childObserver?.Attach();
                }

                if (_adapter.Communicator.TraceLevels.Protocol >= 1)
                {
                    ProtocolTrace.TraceCollocatedFrame(_adapter.Communicator,
                                                       (byte)Ice1Definitions.FrameType.Request,
                                                       requestId,
                                                       outgoingRequestFrame);
                }
            }

            Task <IncomingResponseFrame?> task;

            if (_adapter.TaskScheduler != null || !synchronous || oneway || _reference.InvocationTimeout > 0)
            {
                // Don't invoke from the user thread if async or invocation timeout is set. We also don't dispatch
                // oneway from the user thread to match the non-collocated behavior where the oneway synchronous
                // request returns as soon as it's sent over the transport.
                task = Task.Factory.StartNew(() => InvokeAllAsync(outgoingRequestFrame, requestId, cancel),
                                             cancel,
                                             TaskCreationOptions.None,
                                             _adapter.TaskScheduler ?? TaskScheduler.Default).Unwrap();

                if (oneway)
                {
                    childObserver?.Detach();
                    return(default);
Пример #2
0
        public async ValueTask <IncomingResponseFrame> SendRequestAsync(
            OutgoingRequestFrame outgoingRequest,
            bool oneway,
            bool synchronous,
            IInvocationObserver?observer,
            IProgress <bool> progress,
            CancellationToken cancel)
        {
            cancel.ThrowIfCancellationRequested();

            IChildInvocationObserver?childObserver = null;
            int requestId = 0;

            // The CollocatedRequestHandler is an internal object so it's safe to lock (this) as long as our
            // code doesn't use the collocated request handler as a lock. The lock here is useful to ensure
            // the protocol trace and observer call is output or called in the same order as the request ID
            // is allocated.
            lock (_mutex)
            {
                if (!oneway)
                {
                    requestId = ++_requestId;
                }

                if (observer != null)
                {
                    childObserver = observer.GetCollocatedObserver(_adapter, requestId, outgoingRequest.Size);
                    childObserver?.Attach();
                }

                if (_adapter.Communicator.TraceLevels.Protocol >= 1)
                {
                    ProtocolTrace.TraceCollocatedFrame(_adapter.Communicator,
                                                       (byte)Ice1Definitions.FrameType.Request,
                                                       requestId,
                                                       outgoingRequest);
                }
            }

            Task <OutgoingResponseFrame> task;

            if (_adapter.TaskScheduler != null || !synchronous || oneway || _reference.InvocationTimeout > 0)
            {
                // Don't invoke from the user thread if async or invocation timeout is set. We also don't dispatch
                // oneway from the user thread to match the non-collocated behavior where the oneway synchronous
                // request returns as soon as it's sent over the transport.
                task = Task.Factory.StartNew(() =>
                {
                    progress.Report(false);
                    return(DispatchAsync(outgoingRequest, requestId, cancel));
                },
                                             cancel,
                                             TaskCreationOptions.None,
                                             _adapter.TaskScheduler ?? TaskScheduler.Default).Unwrap();

                if (oneway)
                {
                    childObserver?.Detach();
                    return(IncomingResponseFrame.WithVoidReturnValue(outgoingRequest.Protocol,
                                                                     outgoingRequest.Encoding));
                }
            }
            else // Optimization: directly call DispatchAsync
            {
                Debug.Assert(!oneway);
                progress.Report(false);
                task = DispatchAsync(outgoingRequest, requestId, cancel);
            }

            try
            {
                OutgoingResponseFrame outgoingResponseFrame = await task.WaitAsync(cancel).ConfigureAwait(false);

                var incomingResponseFrame = new IncomingResponseFrame(
                    outgoingRequest.Protocol,
                    VectoredBufferExtensions.ToArray(outgoingResponseFrame.Data),
                    _adapter.IncomingFrameSizeMax);

                if (_adapter.Communicator.TraceLevels.Protocol >= 1)
                {
                    ProtocolTrace.TraceCollocatedFrame(_adapter.Communicator,
                                                       (byte)Ice1Definitions.FrameType.Reply,
                                                       requestId,
                                                       incomingResponseFrame);
                }

                childObserver?.Reply(incomingResponseFrame.Size);
                return(incomingResponseFrame);
            }
            catch (Exception ex)
            {
                childObserver?.Failed(ex.GetType().FullName ?? "System.Exception");
                throw;
            }
            finally
            {
                childObserver?.Detach();
            }
        }