comparison Util/WorkQueue.cs @ 66:b7bc27c6734e

Added WorkQueue class
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 15 Oct 2013 16:22:54 +0200
parents
children 5d1b72ba44dc
comparison
equal deleted inserted replaced
65:abe0d55a2201 66:b7bc27c6734e
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Windows.Forms;
5 using SysThreadPool = System.Threading.ThreadPool;
6
7 namespace UCIS.Util {
8 public class WorkQueue : WorkQueue<MethodInvoker> {
9 public WorkQueue() : base(Handler) { }
10 private static void Handler(MethodInvoker item) { item(); }
11 }
12 public class WorkQueue<TWork> : IDisposable {
13 Queue<TWork> queue = new Queue<TWork>();
14 Action<TWork> callback = null;
15 int maxIdleWorkers = 0;
16 int maxWorkers = 1;
17 int idleWorkers = 0;
18 int workers = 0;
19
20 public Boolean UseFrameworkThreadpool { get; set; }
21
22 public WorkQueue(Action<TWork> callback) {
23 this.callback = callback;
24 UseFrameworkThreadpool = true;
25 }
26 public void Dispose() {
27 maxWorkers = 0;
28 lock (queue) Monitor.PulseAll(queue);
29 }
30
31 public int MaxIdleWorkers {
32 get { return maxIdleWorkers; }
33 set {
34 maxIdleWorkers = value;
35 lock (queue) Monitor.PulseAll(queue);
36 }
37 }
38 public int MaxWorkers {
39 get { return maxWorkers; }
40 set {
41 maxWorkers = value;
42 lock (queue) Monitor.PulseAll(queue);
43 }
44 }
45 public int TotalWorkers { get { return workers; } }
46 public int IdleWorkers { get { return idleWorkers; } }
47
48 public void Enqueue(TWork item) {
49 lock (queue) {
50 queue.Enqueue(item);
51 Monitor.Pulse(queue);
52 if (workers < maxWorkers && idleWorkers == 0) StartWorker();
53 }
54 }
55 public void Clear() { lock (queue) queue.Clear(); }
56 public int Count { get { lock (queue) return queue.Count; } }
57
58 private void StartWorker() {
59 lock (queue) {
60 if (workers >= maxWorkers) return;
61 if (UseFrameworkThreadpool) {
62 SysThreadPool.QueueUserWorkItem(Worker);
63 } else {
64 (new Thread(Worker)).Start();
65 }
66 workers++;
67 }
68 }
69 private void RaiseEvent(Action<WorkQueue<TWork>> callback) {
70 if (callback != null) callback(this);
71 }
72 private void Worker(Object state) {
73 while (true) {
74 TWork item;
75 lock (queue) {
76 if (workers >= maxWorkers) {
77 workers--;
78 break;
79 }
80 if (queue.Count == 0) {
81 if (idleWorkers >= maxIdleWorkers) {
82 workers--;
83 queue.TrimExcess();
84 break;
85 }
86 idleWorkers++;
87 Monitor.Wait(queue);
88 idleWorkers--;
89 if (queue.Count == 0) continue;
90 }
91 item = queue.Dequeue();
92 }
93 callback(item);
94 }
95 }
96 }
97 }