public void EnqueueTask(ThreadWrapperBase task) { lock (workersQueued) { workersQueued.Add(task); } }
public void EnqueueTask(ThreadWrapperBase task) { lock (workersQueued) { workersQueued.Add(task); } }
private void AllocateWork() { while (true) { // Remove completed tasks. // Because we are not using foreach, the collection // doesn't need to be locked. It could grow while this // method is working, but that would only result in a // slot being missed until the next pass, which is acceptable. // It can't shrink, because no other methods remove work. // We count in reverse order so a single pass can // remove multiple entries without rearranging the items // that haven't been scanned. // Deferring the locking improves performance. for (int i = workers.Count - 1; i >= 0; i--) { if (workers[i].Status == StatusState.Completed) { ThreadWrapperBase worker = workers[i]; lock (workersCompleted) { workersCompleted.Add(worker); } lock (workers) { workers.Remove(worker); } // Fire notification event. invokeContext.Invoke(new WorkerCompletedEventHandler(OnWorkerCompleted), new object[] { this, new WorkerCompletedEventArgs((EratosthenesTask)worker) }); } } // Allocate new work while threads are available. while (workersQueued.Count > 0 && workers.Count < maxThreads) { ThreadWrapperBase task = workersQueued[0]; // Some exception handling code here would be useful // to prevent performing one part of this sequence // (starting the task), without the other (removing it // from the queue). lock (workers) { workers.Add(task); } lock (workersQueued) { workersQueued.RemoveAt(0); } task.Start(); } // Report progress. for (int i = workers.Count - 1; i >= 0; i--) { ThreadWrapperBase worker = workers[i]; if (worker.Status == StatusState.InProgress) { // Fire notification event. if (invokeContext.Created) { invokeContext.Invoke(new ReportWorkerProgressEventHandler(OnReportWorkerProgress), new object[] { this, new ReportWorkerProgressEventArgs(worker.ID, worker.Progress) }); } } } // Pause 2 seconds before the next pass. // You could make this variable configurable. Thread.Sleep(TimeSpan.FromSeconds(2)); } }