using System.Threading.Tasks;
using System.Collections.Concurrent;
public class JobDistributor
public Task? RunningTask {get; private set;}
DateTime? TimeOfStart {get; set;}
readonly SemaphoreSlim _semaphore = new(1,1);
public async Task<Task> StartOrGetTheRunningJobAsync()
var requestedStartDate = DateTime.UtcNow;
if (RunningTask is null || RunningTask.IsCompleted)
await _semaphore.WaitAsync();
Console.WriteLine($"Semaphore acquired");
if (RunningTask is null || RunningTask.IsCompleted)
RunningTask = RunJobAsync();
TimeOfStart = DateTime.UtcNow;
if (RunningTask is not null && !RunningTask.IsCompleted && TimeOfStart.Value.Ticks >= requestedStartDate.Ticks){
Console.WriteLine($"Old task is running, waiting...");
private static readonly ConcurrentDictionary<int, JobDistributor> _jobs = new()
public static async Task Main()
var jobDistributor = _jobs[0];
jobDistributor.StartOrGetTheRunningJobAsync();
Task[] sameTimeRequests = new[]
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync()
Task.WaitAll(sameTimeRequests);
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync(),
jobDistributor.StartOrGetTheRunningJobAsync()
Task.WaitAll(sameTimeRequests);
await jobDistributor.RunningTask;
public static async Task RunJobAsync(){
Console.WriteLine($"Finished process: {Guid.NewGuid()}");
public async Task BasicUsageWouldBe()
var runningJobTask = await _jobs[0].StartOrGetTheRunningJobAsync();