using System; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; namespace NCC.FriendlyException { /// /// 重试类 /// public sealed class Retry { /// /// 重试有异常的方法,还可以指定特定异常 /// /// /// 重试次数 /// 重试间隔时间 /// 是否最终抛异常 /// 异常类型,可多个 public static void Invoke(Action action, int numRetries, int retryTimeout = 1000, bool finalThrow = true, Type[] exceptionTypes = default) { if (action == null) throw new ArgumentNullException(nameof(action)); Invoke(async () => { action(); await Task.CompletedTask; }, numRetries, retryTimeout, finalThrow, exceptionTypes).GetAwaiter().GetResult(); } /// /// 重试有异常的方法,还可以指定特定异常 /// /// /// 重试次数 /// 重试间隔时间 /// 是否最终抛异常 /// 异常类型,可多个 public static async Task Invoke(Func action, int numRetries, int retryTimeout = 1000, bool finalThrow = true, Type[] exceptionTypes = default) { if (action == null) throw new ArgumentNullException(nameof(action)); // 不断重试 while (true) { try { await action(); break; } catch (Exception ex) { // 如果可重试次数小于或等于0,则终止重试 if (--numRetries < 0) { if (finalThrow) throw; else return; } // 如果填写了 exceptionTypes 且异常类型不在 exceptionTypes 之内,则终止重试 if (exceptionTypes != null && exceptionTypes.Length > 0 && !exceptionTypes.Any(u => u.IsAssignableFrom(ex.GetType()))) { if (finalThrow) throw; else return; } if (Debugger.IsAttached) { Console.WriteLine($"You can retry {numRetries} more times."); } // 如果可重试异常数大于 0,则间隔指定时间后继续执行 if (retryTimeout > 0) await Task.Delay(retryTimeout); } } } } }