78 lines
2.6 KiB
C#
78 lines
2.6 KiB
C#
|
|
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; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 在指定超时时间内轮询等待条件成立。
|
|||
|
|
/// 当 <paramref name="timeout"/> 为 <c>null</c> 时,表示无限等待,直到条件成立或外部取消。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="condition">待检查的条件,返回 <c>true</c> 表示条件成立。</param>
|
|||
|
|
/// <param name="timeout">最大等待时间。传入 <c>null</c> 表示无限等待;传入具体值时必须大于 0。</param>
|
|||
|
|
/// <param name="pollingInterval">轮询间隔,必须大于 0。</param>
|
|||
|
|
/// <param name="cancellationToken">用于中止等待流程。</param>
|
|||
|
|
public static WaitForConditionResult WaitForConditionWithTimeout(Func<bool> 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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|