我想运行一个具有“心跳”的任务,该任务以特定的时间间隔持续运行,直到任务完成。
我在想这样的扩展方法会很好用:
public static async Task WithHeartbeat(this Task primaryTask, TimeSpan heartbeatInterval, Action<CancellationToken> heartbeatAction, CancellationToken cancellationToken)
例如:
public class Program {
public static void Main() {
var cancelTokenSource = new CancellationTokenSource();
var cancelToken = cancelTokenSource.Token;
var longRunningTask = Task.Factory.StartNew(SomeLongRunningTask, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
var withHeartbeatTask = longRunningTask.WithHeartbeat(TimeSpan.FromSeconds(1), PerformHeartbeat, cancelToken);
withHeartbeatTask.Wait();
Console.WriteLine("Long running task completed!");
Console.ReadLine()
}
private static void SomeLongRunningTask() {
Console.WriteLine("Starting long task");
Thread.Sleep(TimeSpan.FromSeconds(9.5));
}
private static int _heartbeatCount = 0;
private static void PerformHeartbeat(CancellationToken cancellationToken) {
Console.WriteLine("Heartbeat {0}", ++_heartbeatCount);
}
}
该程序应输出:
Starting long task
Heartbeat 1
Heartbeat 2
Heartbeat 3
Heartbeat 4
Heartbeat 5
Heartbeat 6
Heartbeat 7
Heartbeat 8
Heartbeat 9
Long running task completed!
请注意,它不应该(在正常情况下)输出“Heartbeat 10”,因为心跳在初始超时(即 1 秒)之后开始。同样,如果任务花费的时间少于心跳间隔,则根本不应该发生心跳。
什么是实现这一点的好方法?
背景信息:我有一个正在侦听 Azure服务总线队列的服务。我不想在完成处理之前完成消息(这会将其从队列中永久删除),这可能需要比最长消息LockDuration 5 分钟更长的时间。因此,我需要使用这种心跳方法在锁定持续时间到期之前调用RenewLockAsync,以便在进行长时间处理时消息不会超时。