annotate ThreadPool.cs @ 9:9533a87363f3

Fixed deadlock in QueuedPacketStream
author Ivo Smits <Ivo@UCIS.nl>
date Fri, 18 Jan 2013 16:29:50 +0100
parents 4b78cc5f116b
children 1474f92cf7e7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1 ???using System;
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
2 using System.Collections.Generic;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
3 using System.Collections.ObjectModel;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
4 using System.Threading;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
5
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
6 namespace UCIS {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
7 public class ThreadPool {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
8 private static ThreadPool pManager = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
9
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
10 public static ThreadPool DefaultPool {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
11 get {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
12 if (pManager == null) pManager = new ThreadPool();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
13 return pManager;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
14 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
15 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
16
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
17 //Starts a long-term background task
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
18 public static WorkItem RunTask(WaitCallback Callback, object State) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
19 return DefaultPool.QueueWorkItem(Callback, State);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
20 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
21 //Starts a short-term background task
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
22 public static WorkItem RunCall(WaitCallback Callback, object State) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
23 return DefaultPool.QueueWorkItem(Callback, State);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
24 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
25
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
26
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
27 public class WorkItem {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
28 public WaitCallback Callback { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
29 public object State { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
30 public ThreadInfo Thread { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
31 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
32 public class ThreadInfo {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
33 public Thread Thread { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
34 internal AutoResetEvent WaitHandle = new AutoResetEvent(false);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
35 public WorkItem WorkItem { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
36 public bool Busy { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
37 public bool Abort { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
38 public DateTime LastActive { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
39 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
40
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
41 public class ExceptionEventArgs : EventArgs {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
42 public ExceptionEventArgs(WorkItem Item, Exception Exception, bool ThrowError) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
43 this.Item = Item;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
44 this.Exception = Exception;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
45 this.ThrowError = ThrowError;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
46 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
47 public WorkItem Item;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
48 public Exception Exception;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
49 public bool ThrowError;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
50 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
51
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
52 private List<ThreadInfo> pThreads = new List<ThreadInfo>();
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
53 private int pBusyThreads = 0;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
54 private Queue<ThreadInfo> pIdleThreads = new Queue<ThreadInfo>();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
55 private int pThreadsMax;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
56 private int pThreadsMinIdle;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
57 private int pThreadsMaxIdle;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
58
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
59 public event OnExceptionEventHandler OnException;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
60 public delegate void OnExceptionEventHandler(ThreadPool sender, ExceptionEventArgs e);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
61
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
62 public ReadOnlyCollection<ThreadInfo> Threads { get { return pThreads.AsReadOnly(); } }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
63
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
64 public ThreadPool() : this(250, 0, 5) { }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
65
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
66 public ThreadPool(int MaxThreads, int MinIdle, int MaxIdle) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
67 if (MaxThreads < 0) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
68 throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than 0");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
69 } else if (MaxThreads < MaxIdle) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
70 throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must be greater than or equal to ThreadsMaxIdle");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
71 } else if (MaxIdle < 0) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
72 throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than or equal to 0");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
73 } else if (MinIdle < 0) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
74 throw new ArgumentOutOfRangeException("ThreadsMinIdle", "ThreadsMinIdle must greater than or equal to 0");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
75 } else if (MinIdle > MaxIdle) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
76 throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must be greater than or equal to ThreadsMinIdle");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
77 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
78 pThreadsMax = MaxThreads;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
79 pThreadsMinIdle = MinIdle;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
80 pThreadsMaxIdle = MaxIdle;
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
81 for (int I = 1; I <= pThreadsMinIdle; I++) {
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
82 StartThread(false);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
83 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
84 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
85
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
86 public int ThreadsIdle { get { return pIdleThreads.Count; } }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
87 public int ThreadsBusy { get { return pBusyThreads; } }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
88 public int ThreadsAlive { get { return pThreads.Count; } }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
89 public int ThreadsMinIdle {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
90 get { return pThreadsMinIdle; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
91 set {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
92 if (value > pThreadsMaxIdle) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
93 throw new ArgumentOutOfRangeException("ThreadsMinIdle", "ThreadsMinIdle must be smaller than ThreadsMaxIdle");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
94 } else if (value < 0) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
95 throw new ArgumentOutOfRangeException("ThreadsMinIdle", "ThreadsMinIdle must greater than or equal to 0");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
96 } else {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
97 int I = 0;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
98 int C = 0;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
99 C = pIdleThreads.Count;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
100 if (value > C) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
101 for (I = C; I <= value - 1; I++) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
102 StartThread(false);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
103 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
104 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
105 pThreadsMinIdle = value;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
106 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
107 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
108 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
109 public int ThreadsMaxIdle {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
110 get { return pThreadsMaxIdle; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
111 set {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
112 if (pThreadsMinIdle > value) throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must be greater than or equal to ThreadsMinIdle");
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
113 if (value < 0) throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than or equal to 0");
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
114 lock (pIdleThreads) {
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
115 while (value > pIdleThreads.Count) {
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
116 ThreadInfo T = pIdleThreads.Dequeue();
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
117 T.Abort = true;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
118 T.WaitHandle.Set();
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
119 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
120 }
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
121 pThreadsMaxIdle = value;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
122 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
123 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
124 public int ThreadsMax {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
125 get { return pThreadsMax; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
126 set {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
127 if (pThreadsMaxIdle > value) throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must be greater than or equal to ThreadsMaxIdle");
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
128 if (value <= 0) throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must greater than 0");
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
129 pThreadsMax = value;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
130 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
131 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
132
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
133 public WorkItem QueueWorkItem(WaitCallback Callback, object State) {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
134 WorkItem WorkItem = new WorkItem() { Callback = Callback, State = State };
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
135 ThreadInfo Thread = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
136 lock (pIdleThreads) {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
137 while (Thread == null && pIdleThreads.Count > 0) {
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
138 Thread = pIdleThreads.Dequeue();
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
139 if (Thread.Abort) Thread = null;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
140 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
141 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
142 if (Thread == null) {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
143 if (pThreads.Count >= pThreadsMax) throw new ThreadStateException("Thread limit exceeded");
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
144 Thread = StartThread(true);
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
145 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
146 Thread.LastActive = DateTime.Now;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
147 WorkItem.Thread = Thread;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
148 Thread.WorkItem = WorkItem;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
149 Thread.WaitHandle.Set();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
150 return WorkItem;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
151 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
152
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
153 private ThreadInfo StartThread(bool Reserved) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
154 ThreadInfo Thread = new ThreadInfo();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
155 Thread.Thread = new Thread(pWorker);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
156 lock (pThreads) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
157 pThreads.Add(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
158 if (!Reserved) pIdleThreads.Enqueue(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
159 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
160 Thread.LastActive = DateTime.Now;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
161 Thread.Thread.Start(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
162 return Thread;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
163 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
164
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
165 public void AbortAllThreads() {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
166 lock (pIdleThreads) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
167 while (pIdleThreads.Count > 0) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
168 ThreadInfo Thread = pIdleThreads.Dequeue();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
169 Thread.Abort = true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
170 Thread.WaitHandle.Set();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
171 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
172 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
173 foreach (ThreadInfo Thread in pThreads.ToArray()) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
174 if (Thread != null && !Thread.Abort) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
175 Thread.Thread.Abort();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
176 Thread.Abort = true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
177 Thread.WaitHandle.Set();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
178 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
179 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
180 pIdleThreads.Clear();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
181 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
182
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
183 //ToDo: add timer to kill old threads periodically
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
184 public void KillOldThreads() {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
185 ThreadInfo Thread;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
186 lock (pIdleThreads) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
187 if (pIdleThreads.Count == 0) return;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
188 Thread = pIdleThreads.Dequeue();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
189 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
190 if (DateTime.Now.Subtract(Thread.LastActive).TotalMinutes > 1) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
191 Thread.Abort = true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
192 Thread.WaitHandle.Set();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
193 } else {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
194 lock (pIdleThreads) pIdleThreads.Enqueue(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
195 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
196 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
197
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
198 private void pWorker(object state) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
199 ThreadInfo Thread = (ThreadInfo)state;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
200 if (Thread == null) throw new ArgumentNullException("state");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
201 try {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
202 while (true) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
203 if (Thread.WaitHandle == null) throw new ArgumentNullException("WaitHandle");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
204 if (!Thread.WaitHandle.WaitOne(1000, false)) {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
205 if (pBusyThreads <= 0) return;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
206 continue;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
207 }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
208 if (Thread.Abort) break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
209
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
210 Thread.Busy = true;
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
211 Interlocked.Increment(ref pBusyThreads);
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
212 try {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
213 if (Thread.WorkItem == null) throw new ArgumentNullException("WorkItem");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
214 if (Thread.WorkItem.Callback == null) throw new ArgumentNullException("WorkItem.Callback");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
215 Thread.WorkItem.Callback.Invoke(Thread.WorkItem.State);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
216 } catch (ThreadAbortException ex) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
217 ExceptionEventArgs e = new ExceptionEventArgs(Thread.WorkItem, ex, false);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
218 if (OnException != null) OnException(this, e);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
219 if (e.ThrowError) Console.WriteLine("ThreadAbortException in ThreadPool thread: " + e.Exception.ToString());
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
220 return;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
221 } catch (Exception ex) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
222 ExceptionEventArgs e = new ExceptionEventArgs(Thread.WorkItem, ex, true);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
223 if (OnException != null) OnException(this, e);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
224 if (e.ThrowError) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
225 Console.WriteLine("Exception in ThreadPool thread: " + e.Exception.ToString());
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
226 throw new Exception("Unhandled exception in work item", e.Exception);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
227 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
228 } finally {
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
229 Interlocked.Decrement(ref pBusyThreads);
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
230 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
231 Thread.WorkItem.Thread = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
232 Thread.WorkItem = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
233 Thread.Busy = false;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
234 lock (pIdleThreads) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
235 if (pIdleThreads.Count >= pThreadsMaxIdle) break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
236 pIdleThreads.Enqueue(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
237 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
238 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
239 } finally {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
240 Thread.Abort = true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
241 lock (pThreads) pThreads.Remove(Thread);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
242 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
243 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
244 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
245 }