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);
}
}
}
}