From e1a5c360ac09e7950d44d75f6c58b367a5ca385d Mon Sep 17 00:00:00 2001
From: 2dust <31833384+2dust@users.noreply.github.com>
Date: Mon, 6 Jul 2026 11:49:54 +0800
Subject: [PATCH] Optimize timeout logic, try fix
https://github.com/2dust/v2rayN/issues/9681
---
.../ServiceLib/Handler/ConnectionHandler.cs | 7 ++--
v2rayN/ServiceLib/Helper/DownloaderHelper.cs | 38 +++++++++++--------
v2rayN/ServiceLib/Services/DownloadService.cs | 24 ++++++++----
.../ServiceLib/Services/SpeedtestService.cs | 2 +-
4 files changed, 44 insertions(+), 27 deletions(-)
diff --git a/v2rayN/ServiceLib/Handler/ConnectionHandler.cs b/v2rayN/ServiceLib/Handler/ConnectionHandler.cs
index a59421e8..80d9d4e7 100644
--- a/v2rayN/ServiceLib/Handler/ConnectionHandler.cs
+++ b/v2rayN/ServiceLib/Handler/ConnectionHandler.cs
@@ -38,7 +38,7 @@ public static class ConnectionHandler
for (var i = 0; i < 2; i++)
{
- responseTime = await GetRealPingTime(webProxy, 10);
+ responseTime = await GetRealPingTime(webProxy);
if (responseTime > 0)
{
break;
@@ -66,7 +66,7 @@ public static class ConnectionHandler
///
/// Measures response time by sending HTTP requests through proxy.
///
- public static async Task GetRealPingTime(IWebProxy? webProxy, int downloadTimeout)
+ public static async Task GetRealPingTime(IWebProxy? webProxy, int downloadTimeout = 9)
{
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
var responseTime = -1;
@@ -77,7 +77,8 @@ public static class ConnectionHandler
using var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy,
- UseProxy = webProxy != null
+ UseProxy = webProxy != null,
+ ConnectTimeout = TimeSpan.FromSeconds(3)
});
List oneTime = [];
diff --git a/v2rayN/ServiceLib/Helper/DownloaderHelper.cs b/v2rayN/ServiceLib/Helper/DownloaderHelper.cs
index 71c3edbe..d65884b0 100644
--- a/v2rayN/ServiceLib/Helper/DownloaderHelper.cs
+++ b/v2rayN/ServiceLib/Helper/DownloaderHelper.cs
@@ -14,6 +14,8 @@ public class DownloaderHelper
return null;
}
+ var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
+
Uri uri = new(url);
//Authorization Header
var headers = new WebHeaderCollection();
@@ -27,12 +29,12 @@ public class DownloaderHelper
BlockTimeout = timeout * 1000,
MaxTryAgainOnFailure = 2,
RequestConfiguration =
- {
- Headers = headers,
- UserAgent = userAgent,
- ConnectTimeout = timeout * 1000,
- Proxy = webProxy
- }
+ {
+ Headers = headers,
+ UserAgent = userAgent,
+ ConnectTimeout = connectTimeout * 1000,
+ Proxy = webProxy
+ }
};
await using var downloader = new Downloader.DownloadService(downloadOpt);
@@ -45,7 +47,9 @@ public class DownloaderHelper
};
using var cts = new CancellationTokenSource();
- await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
+ cts.CancelAfter(TimeSpan.FromSeconds(timeout));
+
+ await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
using StreamReader reader = new(stream);
downloadOpt = null;
@@ -60,15 +64,16 @@ public class DownloaderHelper
throw new ArgumentNullException(nameof(url));
}
+ var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
var downloadOpt = new DownloadConfiguration()
{
BlockTimeout = timeout * 1000,
MaxTryAgainOnFailure = 2,
RequestConfiguration =
- {
- ConnectTimeout= timeout * 1000,
- Proxy = webProxy
- }
+ {
+ ConnectTimeout= connectTimeout * 1000,
+ Proxy = webProxy
+ }
};
var lastUpdateTime = DateTime.Now;
@@ -116,7 +121,7 @@ public class DownloaderHelper
};
//progress.Report("......");
using var cts = new CancellationTokenSource();
- cts.CancelAfter(timeout * 1000);
+ cts.CancelAfter(TimeSpan.FromSeconds(timeout));
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
downloadOpt = null;
@@ -137,15 +142,16 @@ public class DownloaderHelper
File.Delete(fileName);
}
+ var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
var downloadOpt = new DownloadConfiguration()
{
BlockTimeout = timeout * 1000,
MaxTryAgainOnFailure = 2,
RequestConfiguration =
- {
- ConnectTimeout= timeout * 1000,
- Proxy = webProxy
- }
+ {
+ ConnectTimeout= connectTimeout * 1000,
+ Proxy = webProxy
+ }
};
var progressPercentage = 0;
diff --git a/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayN/ServiceLib/Services/DownloadService.cs
index 1dbdfae2..5db4de7a 100644
--- a/v2rayN/ServiceLib/Services/DownloadService.cs
+++ b/v2rayN/ServiceLib/Services/DownloadService.cs
@@ -109,9 +109,10 @@ public class DownloadService
///
public async Task TryDownloadString(string url, IWebProxy? webProxy, string userAgent)
{
+ var timeout = 15;
try
{
- var result1 = await DownloadStringAsync(url, webProxy, userAgent, 15);
+ var result1 = await DownloadStringAsync(url, webProxy, userAgent, timeout);
if (result1.IsNotEmpty())
{
return result1;
@@ -129,7 +130,7 @@ public class DownloadService
try
{
- var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, 15);
+ var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, timeout);
if (result2.IsNotEmpty())
{
return result2;
@@ -155,11 +156,18 @@ public class DownloadService
{
try
{
- var client = new HttpClient(new SocketsHttpHandler()
+ var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
+ var handler = new SocketsHttpHandler
{
Proxy = webProxy,
- UseProxy = webProxy != null
- });
+ UseProxy = webProxy != null,
+ ConnectTimeout = TimeSpan.FromSeconds(connectTimeout)
+ };
+
+ using var client = new HttpClient(handler)
+ {
+ Timeout = Timeout.InfiniteTimeSpan
+ };
if (userAgent.IsNullOrEmpty())
{
@@ -175,8 +183,9 @@ public class DownloadService
}
using var cts = new CancellationTokenSource();
- var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
- return result;
+ cts.CancelAfter(TimeSpan.FromSeconds(timeout));
+
+ return await client.GetStringAsync(url, cts.Token);
}
catch (Exception ex)
{
@@ -187,6 +196,7 @@ public class DownloadService
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
+
return null;
}
diff --git a/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayN/ServiceLib/Services/SpeedtestService.cs
index 1adf3713..44e95fcb 100644
--- a/v2rayN/ServiceLib/Services/SpeedtestService.cs
+++ b/v2rayN/ServiceLib/Services/SpeedtestService.cs
@@ -420,7 +420,7 @@ public class SpeedtestService(Config config, Func updateF
private async Task DoRealPing(ServerTestItem it)
{
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
- var responseTime = await ConnectionHandler.GetRealPingTime(webProxy, 10);
+ var responseTime = await ConnectionHandler.GetRealPingTime(webProxy);
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
await UpdateFunc(it.IndexId, responseTime.ToString());