Skip to content

Instantly share code, notes, and snippets.

@dadhi
Created September 26, 2023 16:49
Show Gist options
  • Save dadhi/050a633e8d3f5b3175c029771ef036eb to your computer and use it in GitHub Desktop.
Save dadhi/050a633e8d3f5b3175c029771ef036eb to your computer and use it in GitHub Desktop.
The possible interview question about the work queue in C# // @ThePrimeagen
// ## Dumb-dumb initial solution
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Program
{
public static async Task Main()
{
var p = new LimitedPar<int>(3);
var rnd = new Random(42);
List<Task> awaited = new(5);
for (var i = 0; i < 5; ++i)
{
var j = p.RunAsync(i, async n =>
{
var randomDelay = (int)rnd.NextInt64(1000, 3000);
Console.WriteLine($"Starting job #{n}, expected finish in {randomDelay}ms...");
await Task.Delay(randomDelay);
Console.WriteLine($"Finished job #{n}.");
});
if (!j.IsCompleted)
awaited.Add(j);
}
await Task.WhenAll(awaited);
}
public static class LimitedPar
{
public const int DefaultParLevel = 3;
}
public sealed class LimitedPar<S>
{
public readonly int ParLevel;
private Queue<(Func<S, Task>, S)>? _queue;
private int _currentJobRunning;
public LimitedPar(int parLevel = LimitedPar.DefaultParLevel) =>
ParLevel = parLevel;
public async Task RunAsync(S state, Func<S, Task> job)
{
if (_currentJobRunning < ParLevel)
{
++_currentJobRunning;
try
{
await job.Invoke(state);
}
finally
{
--_currentJobRunning;
}
if (_queue?.TryDequeue(out var next) == true)
{
var (j, s) = next;
++_currentJobRunning;
try
{
await j.Invoke(s);
}
finally
{
--_currentJobRunning;
}
}
}
else
{
_queue ??= new(4);
_queue.Enqueue((job, state));
}
}
}
}
@dadhi
Copy link
Author

dadhi commented Sep 27, 2023

The live playground https://dotnetfiddle.net/xzdOTw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment