Skip to content

Instantly share code, notes, and snippets.

@otto-gebb
Created March 11, 2025 05:48
Show Gist options
  • Save otto-gebb/bff885004521d9dbcaf363be3d4990c8 to your computer and use it in GitHub Desktop.
Save otto-gebb/bff885004521d9dbcaf363be3d4990c8 to your computer and use it in GitHub Desktop.
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