Exemple #1
0
        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);
        }
Exemple #2
0
 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;
 }
Exemple #3
0
        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));
        }
Exemple #4
0
 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);
 }
Exemple #5
0
 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);
 }