main
1using System;
2using System.Collections;
3using System.ComponentModel;
4using System.Diagnostics;
5using System.Security.Permissions;
6using System.Threading;
7
8namespace momoney.service.infrastructure.threading
9{
10 [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
11 public class Synchronizer : ISynchronizeInvoke, IDisposable
12 {
13 readonly WorkerThread worker_thread;
14
15 public Synchronizer()
16 {
17 worker_thread = new WorkerThread(this);
18 }
19
20 public bool InvokeRequired
21 {
22 get { return ReferenceEquals(Thread.CurrentThread, worker_thread); }
23 }
24
25 public IAsyncResult BeginInvoke(Delegate method, object[] args)
26 {
27 var result = new WorkItem(null, method, args);
28 worker_thread.queue_work_item(result);
29 return result;
30 }
31
32 public object EndInvoke(IAsyncResult result)
33 {
34 result.AsyncWaitHandle.WaitOne();
35 return ((WorkItem) result).MethodReturnedValue;
36 }
37
38 public object Invoke(Delegate method, object[] args)
39 {
40 return EndInvoke(BeginInvoke(method, args));
41 }
42
43 ~Synchronizer()
44 {
45 }
46
47 public void Dispose()
48 {
49 worker_thread.kill();
50 }
51
52 class WorkerThread
53 {
54 Thread thread;
55 bool end_loop;
56 readonly Mutex end_loop_mutex;
57 readonly AutoResetEvent item_added;
58 Synchronizer synchronizer;
59 readonly Queue work_item_queue;
60
61 internal WorkerThread(Synchronizer synchronizer)
62 {
63 this.synchronizer = synchronizer;
64 end_loop = false;
65 thread = null;
66 end_loop_mutex = new Mutex();
67 item_added = new AutoResetEvent(false);
68 work_item_queue = new Queue();
69 create_thread(true);
70 }
71
72 internal void queue_work_item(WorkItem work_item)
73 {
74 lock (work_item_queue.SyncRoot)
75 {
76 work_item_queue.Enqueue(work_item);
77 item_added.Set();
78 }
79 }
80
81 bool EndLoop
82 {
83 set
84 {
85 end_loop_mutex.WaitOne();
86 end_loop = value;
87 end_loop_mutex.ReleaseMutex();
88 }
89 get
90 {
91 var result = false;
92 end_loop_mutex.WaitOne();
93 result = end_loop;
94 end_loop_mutex.ReleaseMutex();
95 return result;
96 }
97 }
98
99 Thread create_thread(bool auto_start)
100 {
101 if (thread != null)
102 {
103 Debug.Assert(false);
104 return thread;
105 }
106 thread = new Thread(run) {Name = "Synchronizer Worker Thread"};
107 if (auto_start)
108 {
109 thread.Start();
110 }
111 return thread;
112 }
113
114 void start()
115 {
116 Debug.Assert(thread != null);
117 Debug.Assert(thread.IsAlive == false);
118 thread.Start();
119 }
120
121 bool queue_empty
122 {
123 get
124 {
125 lock (work_item_queue.SyncRoot)
126 {
127 if (work_item_queue.Count > 0)
128 {
129 return false;
130 }
131 return true;
132 }
133 }
134 }
135
136 WorkItem GetNext()
137 {
138 if (queue_empty)
139 {
140 return null;
141 }
142 lock (work_item_queue.SyncRoot)
143 {
144 return (WorkItem) work_item_queue.Dequeue();
145 }
146 }
147
148 void run()
149 {
150 while (EndLoop == false)
151 {
152 while (queue_empty == false)
153 {
154 if (EndLoop)
155 {
156 return;
157 }
158 var workItem = GetNext();
159 workItem.CallBack();
160 }
161 item_added.WaitOne();
162 }
163 }
164
165 public void kill()
166 {
167 //Kill is called on client thread - must use cached thread object
168 Debug.Assert(thread != null);
169 if (thread.IsAlive == false)
170 {
171 return;
172 }
173 EndLoop = true;
174 item_added.Set();
175
176 //Wait for thread to die
177 thread.Join();
178 if (end_loop_mutex != null)
179 {
180 end_loop_mutex.Close();
181 }
182 if (item_added != null)
183 {
184 item_added.Close();
185 }
186 }
187 }
188 }
189}