using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace LB_SmartVision
|
{
|
public sealed class PausableHeartbeatAsync : IAsyncDisposable
|
{
|
private readonly CancellationTokenSource _cts = new();
|
private readonly AsyncManualResetEvent _pauseEvent = new(true); // 初始为已设置(未暂停)
|
private readonly Task _loopTask;
|
private readonly Func<Task> _sendHeartbeatAsync;
|
private readonly TimeSpan _interval;
|
|
public PausableHeartbeatAsync(Func<Task> sendHeartbeatAsync, TimeSpan interval)
|
{
|
_sendHeartbeatAsync = sendHeartbeatAsync;
|
_interval = interval;
|
_loopTask = Task.Run(RunAsync);
|
}
|
|
private async Task RunAsync()
|
{
|
using var timer = new PeriodicTimer(_interval);
|
try
|
{
|
while (await timer.WaitForNextTickAsync(_cts.Token))
|
{
|
// 等待暂停状态解除(若未暂停则立即通过)
|
await _pauseEvent.WaitAsync(_cts.Token);
|
|
try
|
{
|
await _sendHeartbeatAsync();
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"[Async Heartbeat] 异常: {ex.Message}");
|
}
|
}
|
}
|
catch (OperationCanceledException) { }
|
}
|
|
public void Pause() => _pauseEvent.Reset();
|
public void Resume() => _pauseEvent.Set();
|
public async Task StopAsync()
|
{
|
_cts.Cancel();
|
Resume(); // 防止 WaitAsync 永久阻塞
|
await _loopTask.ConfigureAwait(false);
|
}
|
public async ValueTask DisposeAsync()
|
{
|
await StopAsync();
|
_cts.Dispose();
|
}
|
|
// 简单的异步手动重置事件辅助类
|
private class AsyncManualResetEvent
|
{
|
private volatile TaskCompletionSource<bool> _tcs = new();
|
private readonly object _lock = new();
|
|
public AsyncManualResetEvent(bool initialState)
|
{
|
if (initialState) _tcs.TrySetResult(true);
|
}
|
|
public Task WaitAsync(CancellationToken token = default)
|
{
|
return _tcs.Task.WaitAsync(token);
|
}
|
|
public void Set()
|
{
|
lock (_lock)
|
{
|
_tcs.TrySetResult(true);
|
}
|
}
|
|
public void Reset()
|
{
|
lock (_lock)
|
{
|
if (_tcs.Task.IsCompleted)
|
_tcs = new TaskCompletionSource<bool>();
|
}
|
}
|
}
|
}
|
}
|