Пример #1
0
        /// <summary>
        /// 执行请求
        /// <para/>
        /// 需手动调用 <see cref="IFullHttpResponse"/> 的Release方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task <IFullHttpResponse> ExecuteAsync(IFullHttpRequest request, CancellationToken token)
        {
            CheckDisposed();

            Interlocked.Exchange(ref _lastTicks, DateTime.UtcNow.Ticks);

            _requestSetupFunc?.Invoke(request);

            var channel = await GetChannelAsync().ConfigureAwait(false);

            var completionSource = new TaskCompletionSource <IFullHttpResponse>();

            if (token.CanBeCanceled)
            {
                token.Register(() =>
                {
                    _ = CloseChannelAsync().ContinueWith(_ =>
                    {
                        completionSource.TrySetException(new OperationCanceledException());
                    }, TaskScheduler.Default);
                });
            }

            _responseHandler.SetCallback((ctx, innerResponse) =>
            {
                try
                {
                    innerResponse.Retain();
                    completionSource.TrySetResult(innerResponse);
                }
#pragma warning disable CA1031 // 不捕获常规异常类型
                catch (Exception ex)
#pragma warning restore CA1031 // 不捕获常规异常类型
                {
                    completionSource.TrySetException(ex);
                }
            });

            var sendTask = channel.WriteAndFlushAsync(request);

            try
            {
                var response = await completionSource.Task.ConfigureAwait(false);

                return(response);
            }
            finally
            {
                if (!sendTask.IsCompleted)
                {
                    await CloseChannelAsync().ConfigureAwait(false);
                }
            }
        }