【发布时间】:2016-08-02 13:21:31
【问题描述】:
我想运行一个具有“heartbeat”的Task,该heartbeat会在特定的时间间隔内持续运行,直到任务完成。
我认为这样的扩展方法会很好用:
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 Service Bus 队列的服务。我不想Complete 消息(这会将它从队列中永久删除),直到我完成处理它,这可能需要比最长消息LockDuration 5 分钟更长的时间。因此,我需要使用这种心跳方法在锁定持续时间到期之前调用RenewLockAsync,以便在进行长时间处理时消息不会超时。
【问题讨论】:
-
这听起来类似于在异步任务中报告进度(只是触发报告的事情是一个时间间隔,并且没有真正的进度要报告,除了可能是心跳计数)。这些链接中的任何一个都有帮助吗? blogs.msdn.com/b/dotnet/archive/2012/06/06/…stackoverflow.com/questions/15408148/…
-
@TimS。它们很相似,但不是我想要的,尤其是在任务快速完成时从不报告的情况。此外,心跳不知道每个说的进度。但是,我很高兴看到您是否可以实现进度方法以匹配我的扩展 API,并使用更简单的代码获得相同的净效果。
标签: c# .net task-parallel-library async-await azureservicebus