using System; using System.Diagnostics; using System.Threading; namespace MainShell.Common { class TimeoutRetryMechanism { public class WaitForConditionResult { public bool Succeeded { get; set; } public bool TimedOut { get; set; } public bool IsAborted { get; set; } } /// /// 在指定超时时间内轮询等待条件成立。 /// 当 null 时,表示无限等待,直到条件成立或外部取消。 /// /// 待检查的条件,返回 true 表示条件成立。 /// 最大等待时间。传入 null 表示无限等待;传入具体值时必须大于 0。 /// 轮询间隔,必须大于 0。 /// 用于中止等待流程。 public static WaitForConditionResult WaitForConditionWithTimeout(Func condition, TimeSpan? timeout, TimeSpan pollingInterval, CancellationToken cancellationToken) { if (condition == null) { throw new ArgumentNullException(nameof(condition)); } if (timeout.HasValue && timeout.Value <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeout), "timeout must be greater than zero when specified."); } if (pollingInterval <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(pollingInterval), "pollingInterval must be greater than zero."); } var stopwatch = Stopwatch.StartNew(); while (true) { if (condition()) { return new WaitForConditionResult { Succeeded = true }; } if (timeout.HasValue && stopwatch.Elapsed > timeout.Value) { return new WaitForConditionResult { Succeeded = false, TimedOut = true }; } if (cancellationToken.IsCancellationRequested) { return new WaitForConditionResult { Succeeded = false, IsAborted = true }; } Thread.Sleep(pollingInterval); } } } }