From 850fecdff41f31af6217a5a494ae952bd3130082 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:03:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(async):=20=E4=BF=AE=E5=A4=8D=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E6=89=A9=E5=B1=95=E4=B8=AD=E7=9A=84=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=92=8C=E9=87=8D=E8=AF=95=E9=80=BB=E8=BE=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复TimeoutAfter方法中的取消令牌处理逻辑,避免OperationCanceledException被意外捕获 - 修复RetryAsync方法中的参数验证,移除对可空值类型的空值检查 - 为RetryAsync方法添加throwOriginal参数以控制异常抛出行为 - 统一超时处理中的令牌取消方式,使用linkedCts.Cancel()替代timeoutCts.CancelAsync() --- GFramework.Core/extensions/AsyncExtensions.cs | 35 +++++++++++++++---- .../extensions/NumericExtensions.cs | 10 +----- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/GFramework.Core/extensions/AsyncExtensions.cs b/GFramework.Core/extensions/AsyncExtensions.cs index 437752c..edee903 100644 --- a/GFramework.Core/extensions/AsyncExtensions.cs +++ b/GFramework.Core/extensions/AsyncExtensions.cs @@ -36,13 +36,22 @@ public static class AsyncExtensions if (completedTask == delayTask) { - // 优先检查外部取消令牌,若已取消则抛出 OperationCanceledException cancellationToken.ThrowIfCancellationRequested(); throw new TimeoutException($"操作在 {timeout.TotalSeconds} 秒后超时"); } - await timeoutCts.CancelAsync(); - return await task; + await linkedCts.CancelAsync(); + try + { + await task; + } + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested && + timeoutCts.Token.IsCancellationRequested) + { + // ignore + } + + return task.Result; } /// @@ -69,13 +78,20 @@ public static class AsyncExtensions if (completedTask == delayTask) { - // 优先检查外部取消令牌,若已取消则抛出 OperationCanceledException cancellationToken.ThrowIfCancellationRequested(); throw new TimeoutException($"操作在 {timeout.TotalSeconds} 秒后超时"); } - await timeoutCts.CancelAsync(); - await task; + await linkedCts.CancelAsync(); + try + { + await task; + } + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested && + timeoutCts.Token.IsCancellationRequested) + { + // ignore + } } /// @@ -86,6 +102,7 @@ public static class AsyncExtensions /// 最大重试次数 /// 重试间隔 /// 判断是否应该重试的函数,默认对所有异常重试 + /// 当为 true 时直接抛出原始异常,否则包装为 AggregateException /// 任务结果 /// 当 taskFactory 为 null 时抛出 /// 当 maxRetries 小于 0 时抛出 @@ -99,7 +116,8 @@ public static class AsyncExtensions this Func> taskFactory, int maxRetries, TimeSpan delay, - Func? shouldRetry = null) + Func? shouldRetry = null, + bool throwOriginal = false) { ArgumentNullException.ThrowIfNull(taskFactory); @@ -123,6 +141,9 @@ public static class AsyncExtensions } else { + if (throwOriginal) + throw; + throw new AggregateException($"操作在 {attempt} 次重试后仍然失败", ex); } } diff --git a/GFramework.Core/extensions/NumericExtensions.cs b/GFramework.Core/extensions/NumericExtensions.cs index 544d6fe..f2080db 100644 --- a/GFramework.Core/extensions/NumericExtensions.cs +++ b/GFramework.Core/extensions/NumericExtensions.cs @@ -23,10 +23,6 @@ public static class NumericExtensions /// public static T Clamp(this T value, T min, T max) where T : IComparable { - ArgumentNullException.ThrowIfNull(value); - ArgumentNullException.ThrowIfNull(min); - ArgumentNullException.ThrowIfNull(max); - if (min.CompareTo(max) > 0) throw new ArgumentException($"最小值 ({min}) 不能大于最大值 ({max})"); @@ -59,10 +55,6 @@ public static class NumericExtensions /// public static bool Between(this T value, T min, T max, bool inclusive = true) where T : IComparable { - ArgumentNullException.ThrowIfNull(value); - ArgumentNullException.ThrowIfNull(min); - ArgumentNullException.ThrowIfNull(max); - if (min.CompareTo(max) > 0) throw new ArgumentException($"最小值 ({min}) 不能大于最大值 ({max})"); @@ -109,4 +101,4 @@ public static class NumericExtensions return (value - from) / (to - from); } -} +} \ No newline at end of file