public WorkJob Enqueue(WorkJob job) { if (Active) { lock (WorkQueue) { WorkQueue.Enqueue(job); } lock (PendingOrExecutingJobs) { PendingOrExecutingJobs.Add(job); } } else { lock (HeldJobs) { HeldJobs.Add(job); } } job.EqueuedTime = DateTime.UtcNow; job.status = WorkJobStatus.Queued; SpawnWorker(); TotalWork++; return(job); }
public async Task Stop(bool wait = true) { Active = false; if (wait) { WorkJob peekJob = null; while (true) { if (ActiveJobs.Count < this.MaxParallelTasks && peekJob != null) { SpawnWorker(); } lock (PendingOrExecutingJobs) { if (PendingOrExecutingJobs.Count > 0) { peekJob = PendingOrExecutingJobs[0]; } else { if (ActiveJobs.Count == 0) { break; } } } if (peekJob != null && ActiveJobs.Count < Math.Min(this.MaxParallelTasks, WorkQueue.Count)) { SpawnWorker(); } if (peekJob != null && peekJob.status != WorkJobStatus.Finished) { await peekJob; } else { lock (PendingOrExecutingJobs) { PendingOrExecutingJobs.Remove(peekJob); } lock (ActiveJobs) { ActiveJobs.Remove(peekJob); } } } } IsRunning = false; }
public WorkJob EnqueueTask(Func <ValueTask> a, Func <Exception, ValueTask> exceptionHandler = null, Func <bool, ValueTask> finished = null) { var retv = new WorkJob(a, exceptionHandler, finished); return(Enqueue(retv)); }
public void Enqueue(Func <ValueTask> a, Func <Exception, ValueTask> exceptionHandler = null, Func <bool, ValueTask> finished = null) { var retv = new WorkJob(a, exceptionHandler, finished); var t = Enqueue(retv); }
private void SpawnWorker() { ThreadPool.UnsafeQueueUserWorkItem(async _ => { WorkJob job = null; lock (selfLockSpawnWorker2) { lock (WorkQueue) { lock (ActiveJobs) { ActiveJobs.RemoveAll(x => x.status == WorkJobStatus.Finished); if (ActiveJobs.Count < this.MaxParallelTasks && WorkQueue.Count > 0) { job = WorkQueue.Dequeue(); lock (Tasks) { Tasks.Add(job.TaskCompletionSource.Task); } ActiveJobs.Add(job); } } } } if (job?.status == WorkJobStatus.Finished) { Debugger.Break(); } if (job != null) { Stopwatch sw = new Stopwatch(); sw.Start(); var thisWorkerId = workerIds++; Fi.Tech.WriteLineInternal("FTH:WorkQueuer", () => $"Worker {thisWorkerId} started"); try { job.DequeuedTime = DateTime.UtcNow; job.status = WorkJobStatus.Running; await job.action().ConfigureAwait(false); if (job.finished != null) { await job.finished(true).ConfigureAwait(false); } Fi.Tech.WriteLineInternal("FTH:WorkQueuer", () => $"Worker {thisWorkerId} executed OK"); } catch (Exception x) { if (job.handling != null) { await job.handling(x).ConfigureAwait(false); } else { Fi.Tech.Throw(x); } if (job.finished != null) { await job.finished(false).ConfigureAwait(false); } Fi.Tech.WriteLineInternal("FTH:WorkQueuer", () => $"Worker {thisWorkerId} thrown an Exception: {x.Message}"); } finally { try { sw.Stop(); lock (this) { job.CompletedTime = DateTime.UtcNow; job.status = WorkJobStatus.Finished; job.TaskCompletionSource.SetResult(0); WorkDone++; job.CompletionTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); this.TotalTaskResolutionTime += (decimal)sw.Elapsed.TotalMilliseconds; lock (ActiveJobs) { if (ActiveJobs.Contains(job)) { if (!ActiveJobs.Remove(job)) { Debugger.Break(); } } } lock (PendingOrExecutingJobs) { if (PendingOrExecutingJobs.Contains(job)) { if (!PendingOrExecutingJobs.Remove(job)) { Debugger.Break(); } } } lock (Tasks) { Tasks.Remove(job.TaskCompletionSource.Task); } if (WorkQueue.Count > 0) { SpawnWorker(); } } } catch (Exception x) { Debugger.Break(); } Fi.Tech.WriteLineInternal("FTH:WorkQueuer", () => $"Worker {thisWorkerId} cleanup OK"); } } }, null); }