Created
August 3, 2020 17:14
-
-
Save rianjs/6832e6ee8e398552a81991e1a47aa0f8 to your computer and use it in GitHub Desktop.
Loop services framework in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading.Tasks; | |
namespace Scratch | |
{ | |
public interface IWorker | |
{ | |
Task DoWorkAsync(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.Logging; | |
namespace Scratch | |
{ | |
public class LoopAgent | |
{ | |
public string Name { get; } | |
private readonly IWorker _worker; | |
private readonly TimeSpan _loopDelay; | |
private readonly CancellationToken _ct; | |
private readonly ILogger _logger; | |
/// <param name="loopDelay">Duration to wait before running the loop again. If the loop is meant to run every 3 seconds, and the previous iteration took | |
/// 2 seconds, the wait will be 1 second. If the previous iteration took 4 seconds, the wait will be zero.</param> | |
public LoopAgent(string name, IWorker worker, TimeSpan loopDelay, CancellationToken ct, ILogger logger) | |
{ | |
Name = name; | |
_worker = worker; | |
_loopDelay = loopDelay > TimeSpan.Zero | |
? loopDelay | |
: TimeSpan.Zero; | |
_ct = ct; | |
_logger = logger; | |
} | |
public async Task LoopAsync() | |
{ | |
while (!_ct.IsCancellationRequested) | |
{ | |
_logger.LogInformation($"Starting {Name} work loop"); | |
var timer = Stopwatch.StartNew(); | |
try | |
{ | |
await _worker.DoWorkAsync(); | |
} | |
catch (Exception e) | |
{ | |
_logger.LogError(e, "Loop threw an exception"); | |
} | |
timer.Stop(); | |
_logger.LogInformation($"Finished {Name} work loop in {timer.Elapsed}"); | |
var sleepDelay = GetSleepDelay(_loopDelay, timer.Elapsed); | |
await Task.Delay(sleepDelay); | |
} | |
} | |
internal static TimeSpan GetSleepDelay(TimeSpan delay, TimeSpan elapsed) | |
{ | |
var toWait = delay - elapsed; | |
return toWait > TimeSpan.Zero | |
? toWait | |
: TimeSpan.Zero; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.Logging.Abstractions; | |
using ILogger = Microsoft.Extensions.Logging.ILogger; | |
namespace Scratch | |
{ | |
public class PrintTime : IWorker | |
{ | |
private int counter = 0; | |
public async Task DoWorkAsync() | |
{ | |
Console.WriteLine($"{counter++:N0})\t{DateTime.UtcNow:O}"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.Logging.Abstractions; | |
using ILogger = Microsoft.Extensions.Logging.ILogger; | |
namespace Scratch | |
{ | |
class Program | |
{ | |
private static CancellationTokenSource _cts = new CancellationTokenSource(); | |
private static ILogger _logger = new NullLogger<Program>(); | |
public static async Task Main() | |
{ | |
var oneSecond = new PrintTime(); | |
var threeSeconds = new PrintTime(); | |
var loopAgents = new List<LoopAgent> | |
{ | |
new LoopAgent("1 second delay", oneSecond, TimeSpan.FromSeconds(1), _cts.Token, _logger), | |
new LoopAgent("3 second delay", threeSeconds, TimeSpan.FromSeconds(3), _cts.Token, _logger), | |
}; | |
await Task.WhenAll(loopAgents.Select(a => a.LoopAsync())); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment