using System.Threading.Tasks;
public static async Task Main()
using var cts = new CancellationTokenSource();
var workloadTasks = Enumerable.Range(0, 40).Select(_ => Task.Run(() => ProduceLoadAsync(cts.Token))).ToArray();
using var watchdogCts = new CancellationTokenSource(2000);
await Task.Run(() => DoTheWatchdogAsync(watchdogCts.Token));
Console.WriteLine(ex.Message);
await Task.WhenAll(workloadTasks);
Console.WriteLine("Exited");
private static void DoTheWatchdog(CancellationToken cancellationToken = default)
void gRPCSend(CancellationToken cancellationToken = default) => Thread.Sleep(30);
void gRPCReceive(CancellationToken cancellationToken = default) => Thread.Sleep(30);
while (!cancellationToken.IsCancellationRequested)
var start = DateTime.UtcNow;
gRPCSend(cancellationToken);
gRPCReceive(cancellationToken);
var end = DateTime.UtcNow;
if ((end - start).TotalMilliseconds >= 100)
Console.WriteLine("Watchdog alert!");
throw new InvalidOperationException("Watchdog alert!");
private static async Task DoTheWatchdogAsync(CancellationToken cancellationToken = default)
async Task gRPCSendAsync(CancellationToken cancellationToken = default) => await Task.Yield();
async Task gRPCReceiveAsync(CancellationToken cancellationToken = default) => await Task.Yield();
while (!cancellationToken.IsCancellationRequested)
var start = DateTime.UtcNow;
await gRPCSendAsync(cancellationToken).ConfigureAwait(false);
await gRPCReceiveAsync(cancellationToken).ConfigureAwait(false);
var end = DateTime.UtcNow;
if ((end - start).TotalMilliseconds >= 100)
throw new InvalidOperationException("Watchdog alert!");
private static async Task ProduceLoadAsync(CancellationToken cancellationToken = default)
while (!cancellationToken.IsCancellationRequested)
for (var i = 0; i < 1000000 && !cancellationToken.IsCancellationRequested; ++i)