Я хотел бы запустить 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 до истечения времени блокировки, чтобы сообщение не затягивалось, а длительная обработка происходит.