public void Dispose() { lock (workersSync) { exit = true; foreach (WorkerWrapper worker in usedWorkers) { worker.Dispose(); } for (int i = 0; i < 5 && usedWorkers.Count > 0; i++) { bool workerRemoved = false; for (int j = usedWorkers.Count - 1; j >= 0; j--) { if (usedWorkers [j].IsAlive) { continue; } usedWorkers.RemoveAt(j); workerRemoved = true; } if (workerRemoved) { i = 0; } else { Thread.Sleep(100); } } while (freeWorkers.Count > 0) { WorkerWrapper worker = freeWorkers.Dequeue(); worker.Dispose(); } } if (distributor != null && distributor.IsAlive) { if (!distributor.Join(200)) { distributor.Abort(); } distributor = null; } }
private void DistributorThread() { while (!exit) { JobWrapper job = null; bool entered = false; try { Monitor.Enter(jobsSync); entered = true; if (jobs.Count == 0) { Monitor.Exit(jobsSync); entered = false; jobEnqueued.WaitOne((int)distributorPollWait, false); Monitor.Enter(jobsSync); entered = true; if (exit) { break; } } while (jobs.Count > 0) { job = jobs.Peek(); if (!job.Aborting) { break; } job.Finish(new WorkFinishedEventArgs(ThreadState.Unstarted, null)); jobs.Dequeue(); job = null; } } finally { if (entered) { Monitor.Exit(jobsSync); } } lock (workersSync) { for (int i = usedWorkers.Count - 1; i >= 0; i--) { WorkerWrapper worker = usedWorkers [i]; if (worker.CheckFinished()) { usedWorkers.RemoveAt(i); freeWorkers.Enqueue(worker); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker finished", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif continue; } if (worker.CurrentJob.MaxRunningTime <= worker.CurrentJob.TimeStarted) { worker.StopWork(); usedWorkers.RemoveAt(i); freeWorkers.Enqueue(worker); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker stopped", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } if (!worker.IsAlive) { if (worker.CurrentJob != null && !worker.CurrentJob.IsFinished) { worker.CurrentJob.Finish(new WorkFinishedEventArgs(ThreadState.Aborted, null)); } usedWorkers.RemoveAt(i); freeWorkers.Enqueue(worker); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker died unexpectedly", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } } if (job != null) { WorkerWrapper worker = null; if (freeWorkers.Count == 0) { if (maxWaitBeforeWorkerCreation <= (int)job.TimeEnqueued.TotalMilliseconds && usedWorkers.Count < maxWorkers && !exit) { worker = new WorkerWrapper(this); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker created", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } } else { worker = freeWorkers.Dequeue(); } if (worker != null) { if (worker.StartWork(job)) { lock (jobsSync) { jobs.Dequeue(); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): job dequeued", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } usedWorkers.Add(worker); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker started", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } else { freeWorkers.Enqueue(worker); #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker start failed", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } } } bool workerDisposed = false; do { if (freeWorkers.Count <= minWorkers) { break; } WorkerWrapper worker = freeWorkers.Peek(); if (maxWorkerSleepTime > (int)worker.TimeSleeping.TotalMilliseconds) { continue; } freeWorkers.Dequeue(); worker.Dispose(); workerDisposed = true; #if DEBUG_THREADPOOL Debug.WriteLine(string.Format("{0} > Thread pool (jq:{1}, wu:{2},wf:{3}): worker disposed", DateTime.Now.ToString("HH:mm:ss.ff"), jobs.Count, usedWorkers.Count, freeWorkers.Count)); #endif } while (workerDisposed); } } }