You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8中Android APP断连时HttpContext.RequestAborted未触发取消

问题分析与解决方案

可能原因

  • TCP连接检测延迟:移动端关闭WiFi后,TCP连接不会立即发送终止信号(FIN/RST),Kestrel依赖TCP层的超时机制检测死连接,默认超时时间较长(比如默认IdleTimeout为2分钟),导致RequestAborted令牌无法立即触发。而本地Postman测试时,同一机器内的TCP连接断开会被快速检测到,因此令牌正常工作。
  • Kestrel默认配置不适配移动端场景:默认的连接超时参数未针对移动端不稳定网络优化,无法及时识别连接丢失。
  • 移动端上传未主动取消请求:安卓APP在网络断开后,未主动终止上传请求,导致服务器端仍在等待数据,未触发取消逻辑。

解决方案

1. 调整Kestrel连接超时配置

在Program.cs中修改Kestrel的IdleTimeout和KeepAliveTimeout,缩短连接检测时间:

builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.IdleTimeout = TimeSpan.FromSeconds(30);
    options.Limits.KeepAliveTimeout = TimeSpan.FromSeconds(30);
});

这样服务器会更快检测到长时间无数据传输的死连接,触发RequestAborted。

2. 合并超时令牌与RequestAborted

手动创建超时令牌,和RequestAborted合并,确保即使TCP超时未触发,也能在指定时间内取消操作:

using var cts = CancellationTokenSource.CreateLinkedTokenSource(HttpContext.RequestAborted);
cts.CancelAfter(TimeSpan.FromSeconds(60)); // 设置60秒超时

await using var fileStream = IOFile.Create(filePath, bufferSize: 1024);
try
{
    await fileSection.FileStream?.CopyToAsync(fileStream, cts.Token);
}
catch (OperationCanceledException)
{
    // 处理取消逻辑,比如删除未完成的文件
    if (IOFile.Exists(filePath))
    {
        IOFile.Delete(filePath);
    }
    throw;
}

3. 监听流读取状态辅助判断

在流式上传过程中,额外检查流的读取返回值,如果连续多次读取到0字节,主动触发取消:

await using var fileStream = IOFile.Create(filePath, bufferSize: 1024);
var buffer = new byte[1024];
int bytesRead;
var emptyReadCount = 0;

while ((bytesRead = await fileSection.FileStream.ReadAsync(buffer, 0, buffer.Length, HttpContext.RequestAborted)) > 0)
{
    await fileStream.WriteAsync(buffer, 0, bytesRead, HttpContext.RequestAborted);
    emptyReadCount = 0;
}
// 连续多次空读,判定连接丢失
if (emptyReadCount >= 3)
{
    HttpContext.RequestAborted.ThrowIfCancellationRequested();
    throw new OperationCanceledException("Connection lost due to empty reads");
}

4. 移动端主动取消上传

在安卓APP中监听网络状态变化,当检测到WiFi断开时,主动取消HttpClient的上传请求:

// 安卓端示例(C# .NET for Android)
var httpClient = new HttpClient();
var cts = new CancellationTokenSource();

// 监听网络状态,断开时取消
Connectivity.ConnectivityChanged += (s, e) =>
{
    if (!e.NetworkAccess.HasFlag(NetworkAccess.Internet))
    {
        cts.Cancel();
    }
};

// 执行上传
try
{
    var content = new StreamContent(fileStream);
    await httpClient.PostAsync(uploadUrl, content, cts.Token);
}
catch (OperationCanceledException)
{
    // 处理取消逻辑
}

内容的提问来源于stack exchange,提问作者Iron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:16:13