public async void RunAllJobs() { if (IsRunningJob) { return; } while (true) { IShareJob nextJob = null; // TryDequeue is thread-safe if (!InnerQueue.TryDequeue(out nextJob)) { AllJobsFinished?.Invoke(this, new EventArgs()); return; } nextJob.StatusUpdate += Job_StatusUpdate; nextJob.Finished += NextJob_Finished; IsRunningJob = true; CurrentJob = nextJob; JobStarted?.Invoke(this, new ShareJobQueueStatusEventArgs(nextJob, "Started")); await nextJob.Execute(); // executes NextJob_Finished when finished IsRunningJob = false; CurrentJob.StatusUpdate -= Job_StatusUpdate; } }