取消 HttpConnection.ConnectionCloseReadStream.Read

问题描述 投票:0回答:1

为了提供一些上下文,我正在执行一个 HTTP 请求,其响应预计是一个流。因此,我在从

StreamReader
返回的流之上使用
HttpResponseMessage

最简单的场景

using ( var streamReader = new StreamReader( await httpClient.GetStreamAsync( url, ct ) ) )
{
    while ( !streamReader.EndOfStream && !ct.IsCancellationRequested )
    {
        var line = await streamReader.ReadLineAsync( ct );

        Console.WriteLine( line );
    }
}

所以现在的情况是我有一个超时

CancellationToken
,但是当请求取消时,它不会执行任何操作。
ReadLineAsync
“卡住”是很常见的,因为只有在有新内容时才会传输数据。但因为网络问题不会影响直播,所以我在过了一定时间后添加了取消请求。

再次,最简单的场景

CancellationTokenSource cts = new CancellationTokenSource();
var ct = cts.Token;

ct.Register( () =>
{
    logger.LogInformation( "Cancellation requested." );
} );

运行应用程序,我可以看到请求取消

2023-05-03 06:29:10 info: consoleapp[0] Cancellation requested.

但读者不为所动。

所以我继续查看底层流类型是什么,它是一个

HttpConnection.ConnectionCloseReadStream
。来源可以在这里找到。

看代码,调用

HttpConnection.ReadAsync
方法时似乎没有使用取消令牌。

ValueTask<int> readTask = connection.ReadAsync(buffer);

不确定这是否重要,因为最重要的是我们有

CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

但现实是,它并没有真正发挥作用。

有人对此有任何见解吗?

.net http httpclient
1个回答
0
投票

在您提供的示例(SocketsHttpHandler 的 HttpConnection)中,必须将 CancellationToken 传递到执行管道才能使取消正常工作,并且该区域有一些修复。 (例如 https://github.com/dotnet/corefx/pull/40715https://github.com/dotnet/runtime/pull/686

特别是在 HttpConnection 中,他们还使用 CancellationTokens 注册操作来拆除连接(在某些情况下,可以免除将令牌进一步传递到执行管道)

© www.soinside.com 2019 - 2024. All rights reserved.