Created
March 11, 2025 05:48
-
-
Save otto-gebb/bff885004521d9dbcaf363be3d4990c8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.Channels; | |
var builder = Host.CreateApplicationBuilder(args); | |
builder.Services.AddHostedService<Worker>(); | |
builder.Services.AddSingleton<SettingsQueue>(); | |
var host = builder.Build(); | |
var writer = host.Services.GetRequiredService<SettingsQueue>().Settings.Writer; | |
writer.TryWrite(true); | |
_ = Task.Run(() => { | |
while (true) | |
{ | |
var key = Console.ReadKey(); | |
Console.WriteLine(); | |
if (key.Key == ConsoleKey.E) | |
{ | |
writer.TryWrite(true); | |
} | |
else if (key.Key == ConsoleKey.D) | |
{ | |
writer.TryWrite(false); | |
} | |
else if (key.Key == ConsoleKey.Q) | |
{ | |
writer.Complete(); | |
} | |
} | |
}); | |
Console.WriteLine("Press 'q' to end stream, 'e' to enable, 'd' to disable."); | |
host.Run(); | |
public class SettingsQueue | |
{ | |
public Channel<bool> Settings { get; } = Channel.CreateUnbounded<bool>(); | |
} | |
public class Worker : BackgroundService | |
{ | |
private readonly ILogger<Worker> _logger; | |
private readonly ChannelReader<bool> _settingsReader; | |
public Worker(ILogger<Worker> logger, SettingsQueue settingsQueue) | |
{ | |
_logger = logger; | |
_settingsReader = settingsQueue.Settings.Reader; | |
} | |
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |
{ | |
CancellationTokenSource? cts = null; | |
await foreach (bool enabled in _settingsReader.ReadAllAsync(stoppingToken)) | |
{ | |
cts?.Cancel(); | |
cts?.Dispose(); | |
cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); | |
if (enabled) | |
{ | |
_ = CheckPeriodically(cts.Token); | |
} | |
} | |
cts?.Cancel(); | |
} | |
private async Task CheckPeriodically(CancellationToken token) | |
{ | |
using PeriodicTimer timer = new PeriodicTimer(TimeSpan.FromSeconds(3)); | |
CancellationTokenSource? cts = null; | |
do | |
{ | |
cts?.Cancel(); | |
cts?.Dispose(); | |
cts = CancellationTokenSource.CreateLinkedTokenSource(token); | |
_ = Check(cts.Token); | |
} while (await timer.WaitForNextTickAsync(token)); | |
} | |
private int _i; | |
private async Task Check(CancellationToken token) | |
{ | |
try | |
{ | |
int i = Interlocked.Increment(ref _i); | |
_logger.LogInformation("[{i}] Checking... ", i); | |
await Task.Delay(2000, token); | |
_logger.LogInformation("[{i}] Checked.", i); | |
} | |
catch (Exception ex) when (ex is not OperationCanceledException) | |
{ | |
_logger.LogError(ex, "Error while checking."); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment