factory threads
1 .NET 2.0中真正的多线程实例
2 Real Multi-threading in .NET 2.0
3 remex1980 翻译于 2007-5-16 20:43:21
4 原作者: Jose Luis Latorre
5 原文地址:http://www.codeproject.com/useritems/RealMultiThreading.asp
6
7
8 多线程实例源代码(保留原文处链接)
9 http://www.codeproject.com/useritems/RealMultiThreading/RealMultiThreading_src.zip
10
11
12
13
14
15 简介
16
17 多线程总是那么让人振奋。大家都希望能够同时处理很多事情,不过如果我们没有正确的硬件的话,我们很难达到这点。到目前为止,我们所做的只是分开CPU使用较多的工作,使其为后台进程,这样可以使得界面上不被阻塞。
18
19 不过我希望能够得到更好的效果,并充分利用当前最新的多CPU效能。因此,我将写一个真正的多线程实例,将会有多个线程作为后台线程在运行。
20
21 这就是这篇文章将要写的,不得不说的是,最终的结果实在是让我很激动。希望你也能够发觉它的用处。
22
23 在有4个CPU的多CPU服务器上,我得到了280%的效果(测试的是CPU型的任务),在一些非CPU占用较多的任务中,它可以提高到500% 到1000%的性能。
24
25 背景
26
27 网上也有不少介绍.Net 2.0下的多线程的文章,应该说,我从它们中受益颇多。我正在使用的是BackgroundWorker .Net 2.0组件(不过也有实现在.net 1.1下的代码)。
28
29 这里,我列出一些有用的文章链接:
30 来自Paul Kimmel的很好的介绍性文章 http://www.informit.com/articles/article.asp?p=459619&seqNum=5&rl=1
31 来自Juval Löwy的介绍性文章 http://www.devx.com/codemag/Article/20639/1954?pf=true
32 (必看)Joseph Albahari的C#中使用线程 http://www.albahari.com/threading/part3.html
33 Michael Weinhardt写的在Windows Forms 2.0中一个简单安全的多线程,我使用了这个网页中的CPU密集型任务,这是他从Chris Sell的文章中引用的。
34 http://www.mikedub.net/mikeDubSamples/SafeReallySimpleMultithreadingInWindowsForms20/SafeReallySimpleMultithreadingInWindowsForms20.htm
35
36 如果你对多线程世界仍然不是特别熟悉或者希望了解最新的.Net 2.0的 BackgroundWorker组件,那么应该好好读读上面的文章。
37
38
39
40 提出的问题
41
42 任何一个任务……无论是CPU密集型还是普通的任务:
43
44 CPU密集型:它可以分成一个、两个或多个线程,每个线程会占用一个CPU(这样就使得程序的性能翻番)
45
46 普通任务:每一个顺序执行的普通任务,在进行数据存储或使用一个web service的时候都会有一些延迟。所有的这些,都意味着这些没有使用的时间对于用户或任务本身来说有了浪费。这些时间将被重新安排,并将被并行的任务使用,不会再丢失。也就是说,如果有100个100ms延迟的任务,它们在单线程模型和20个线程模型的性能差距会达到1000%。
47
48
49 我们说,如果要处理一个创建一个网站多个块的任务,不是顺序的执行,而是花1-4秒钟把所有的section创建好;商标,在线用户,最新文章,投票工具等等…… 如果我们能够异步地创建它们,然后在发送给用户,会怎么样?我们就会节省很多webservice的调用,数据库的调用,许多宝贵的时间……这些调用会更快地执行。看上去是不是很诱人?
50
51
52
53 解决方案如下:
54
55 调用BackgroundWorker,正如我们想要的那样,我们会继承它。后台worker会帮助我们建立一个“Worker”,用于异步地做一个工作。
56
57 我们想做的是建立一个工厂Factory(只是为了面向对象的设计,于设计模式无关),任务会放在在这个Factory中执行。这意味着,我们将有一类的任务,一些进程,一些知道如何执行任务的worker。
58
59 当然我们需要一个负责分配任务给这些worker的manager,告诉这些worker当它们做完一步或全部时,做什么事情。当然,我们也需要manager能够告诉worker停止当前的任务。它们也需要休息啊:)当manager说停止的时候,它们就应该停止。
60
61 我们将会从底至上地解释这些,首先从Worker说起,然后再继续Manager。
62
63 Worker
64
65
66 它是Background worker的继承类,我们构建一个构造函数,并分配两个BackgroundWorker的属性,分别是WorkerReportsProgress 和WorkerSupportsCancellation,它们的功能就向其名字的意义一样:报告进度,停止任务。每个Worker还有一个id,Manager将会通过这个id控制它们。
67
68
69 public class MTWorker : BackgroundWorker
70 {
71 #region Private members
72 private int _idxLWorker = 0;
73 #endregion
74
75 #region Properties
76 public int IdxLWorker
77 {
78 get { return _idxLWorker; }
79 set { _idxLWorker = value; }
80 }
81 #endregion
82
83 #region Constructor
84 public MTWorker()
85 {
86 WorkerReportsProgress = true;
87 WorkerSupportsCancellation = true;
88 }
89 public MTWorker(int idxWorker)
90 : this()
91 {
92 _idxLWorker = idxWorker;
93 }
94 #endregion
95
96
97 另外,我们将重载BackgroundWorker的一些函数。事实上,最有意思的是,究竟谁在做真正的工作?它就是OnDoWork,当我们invoke或者启动多线程的时候,它就会被调用。在这里,我们启动任务、执行任务、取消和完成这个任务。
98 我加了两个可能的任务,一个是普通型的,它会申请并等待文件系统、网络、数据库或Webservices的调用。另一个是CPU密集型的任务:计算PI值。你可以试试增加或减少线程数量后,增加或是减少的延迟(我的意思是增减Worker的数量)
99
100
101
102 OnDoWork方法的代码
103
104
105 protected override void OnDoWork(DoWorkEventArgs e)
106 {
107 //Here we receive the necessary data for doing the work
108 //we get an int but it could be a struct, class, whatever..
109 int digits = (int)e.Argument;
110 double tmpProgress = 0;
111 int Progress = 0;
112 String pi = "3";
113
114 // This method will run on a thread other than the UI thread.
115 // Be sure not to manipulate any Windows Forms controls created
116 // on the UI thread from this method.
117 this.ReportProgress(0, pi);
118 //Here we tell the manager that we start the job..
119
120 Boolean bJobFinished = false;
121 int percentCompleteCalc = 0;
122 String TypeOfProcess = "NORMAL"; //Change to "PI" for a cpu intensive task
123 //Initialize calculations
124 while (!bJobFinished)
125 {
126 if (TypeOfProcess == "NORMAL")
127 {
128 #region Normal Process simulation, putting a time
129 delay to emulate a wait-for-something
130 while (!bJobFinished)
131 {
132 if (CancellationPending)
133 {
134 e.Cancel = true;
135 return; //break
136 }
137 //Perform another calculation step
138 Thread.Sleep(250);
139 percentCompleteCalc = percentCompleteCalc + 10;
140 if (percentCompleteCalc >= 100)
141 bJobFinished = true;
142 else
143 ReportProgress(percentCompleteCalc, pi);
144 }
145 #endregion
146 }
147 else
148 {
149 #region Pi Calculation - CPU intensive job,
150 beware of it if not using threading ;) !!
151 //PI Calculation
152 if (digits > 0)
153 {
154 pi += ".";
155 for (int i = 0; i < digits; i += 9)
156 {
157 // Work out pi. Scientific bit :-)
158 int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
159 int digitCount = System.Math.Min(digits - i, 9);
160 string ds = System.String.Format("{0:D9}", nineDigits);
161 pi += ds.Substring(0, digitCount);
162
163 // Show progress
164 tmpProgress = (i + digitCount);
165 tmpProgress = (tmpProgress / digits);
166 tmpProgress = tmpProgress * 100;
167 Progress = Convert.ToInt32(tmpProgress);
168 ReportProgress(Progress, pi);
169 // Deal with possible cancellation
170 if (CancellationPending) //If the manager says to stop, do so..
171 {
172 bJobFinished = true;
173 e.Cancel = true;
174 return;
175 }
176 }
177 }
178 bJobFinished = true;
179 #endregion
180 }
181
182 }
183 ReportProgress(100, pi); //Last job report to the manager ;)
184 e.Result = pi; //Here we pass the final result of the Job
185 }
186 Manager
187
188 这是一个很有趣的地方,我确信它有很大的改进空间-欢迎任何的评论和改进!它所做的是给每个线程生成和配置一个Worker,然后给这些Worker安排任务。目前,传给Worker的参数是数字,但是它能够传送一个包含任务定义的类或结构。一个可能的改进是选择如何做这些内部工作的策略模式。
189
190 调用InitManager方法配置任务,和它的数量等属性。然后,创建一个多线程Worker的数组,配置它们。
191 配置的代码如下:
192
193
194 private void ConfigureWorker(MTWorker MTW)
195 {
196 //We associate the events of the worker
197 MTW.ProgressChanged += MTWorker_ProgressChanged;
198 MTW.RunWorkerCompleted += MTWorker_RunWorkerCompleted;
199 }
200
201 Like this, the Worker’s subclassed thread management Methods are linked to the Methods held by the Manager. Note that with a Strategy pattern implemented we could assign these to the proper manager for these methods.
202 最主要的方法是AssignWorkers,它会检查所有的Worker,如果发现没有任务的Worker,就分配一个任务给它。直到扫描一遍之后,没有发现任何有任务的Worker,这样就意味这任务结束了。不需要再做别的了!
203
204 代码如下:
205
206 public void AssignWorkers()
207 {
208 Boolean ThereAreWorkersWorking = false;
209 //We check all workers that are not doing a job and assign a new one
210 foreach (MTWorker W in _arrLWorker)
211 {
212 if (W.IsBusy == false)
213 {
214 //If there are still jobs to be done
215 //we assign the job to the free worker
216 if (_iNumJobs > _LastSentThread)
217 {
218 //We control the threads associated to a worker
219 //(not meaning the jobs done) just 4 control.
220 _LastSentThread = _LastSentThread + 1;
221 W.JobId = _LastSentThread; //We assign the job number..
222 W.RunWorkerAsync(_iPiNumbers); //We pass the parameters for the job.
223 ThereAreWorkersWorking = true;
224 //We have at least this worker we just assigned the job working..
225 }
226 }
227 else
228 {
229 ThereAreWorkersWorking = true;
230 }
231 }
232
233 if (ThereAreWorkersWorking == false)
234 {
235 //This means that no worker is working and no job has been assigned.
236 //this means that the full package of jobs has finished
237 //We could do something here
238 Button BtnStart = (Button)FormManager.Controls["btnStart"];
239 Button BtnCancel = (Button)FormManager.Controls["btnCancel"];
240 BtnStart.Enabled = true;
241 BtnCancel.Enabled = false;
242 MessageBox.Show("Hi, I'm the manager to the boss (user): " +
243 "All Jobs have finished, boss!!");
244 }
245 }
246
247 只要有任务完成,这个方法就会被调用。从而,保证所有的任务能够完成。
248
249 我们还通过一个属性链接到Form上,这样我们就能向UI上输出我们想要的任何消息了。当然,你可能想链接到其它的一些类,不过这是最基本最通用的。
250
251 Well… improving it we could get a BackgroundManager for all our application needs..
252
253
254
255 界面
256
257 连接到界面上,并不是最主要的功能。这一部分的代码量非常少,也很简单:在Manager中添加一个引用,并在form的构造函数中配置它。
258 在一个按钮中,执行Manager类的LaunchManagedProcess方法。
259
260
261 private MTManager LM;
262 public Form1()
263 {
264 InitializeComponent();
265 LM = new MTManager(this, 25);
266 LM.InitManager();
267 }
268
269 private void btnStart_Click(object sender, EventArgs e)
270 {
271 btnStart.Enabled = false;
272 btnCancel.Enabled = true;
273 LM.LaunchManagedProcess();
274 }
275
276 private void btnCancel_Click(object sender, EventArgs e)
277 {
278 LM.StopManagedProcess();
279 btnCancel.Enabled = false;
280 btnStart.Enabled = true;
281 }
282
283 (下面的自己看喽:)
284 Trying it!
285 This is the funniest part, changing the properties of how many threads to run simultaneously and how many Jobs to be processed and then try it on different CPU’s… ah, and of course, change the calculation method from a CPU-intensive task to a normal task with a operation delay
286 I would love to know your results and what have you done with this, any feedback would be great!!
287
288 Exercises For You…
289 This is not done! It could be a MultiThreadJob Framework if there is being done the following:
290
291 Implement a Strategy pattern that determines the kind of Worker to produce (with a factory pattern) so we will be able to do different kind of jobs inside the same factory.. what about migrating a database and processing each table in a different way… or integrating systems with this engine…
292 Implement -or extend- the strategy pattern for determining the treatment for the Input data and the result data of the jobs. We could too set-up a factory for getting the classes into a operating environment.
293 Optimize the AssignWorkers engine – I am pretty sure it can be improved.
294 Improve the WorkerManager class in order to be able to attach it to another class instead to only a form.
295 Send me the code! I Would love to hear from you and what have you done.
296
297 About Jose Luis Latorre
298
299 Professional developer since 1991, having developed on multiple systems and languages since then, from Unix, as400, lotus notes, flash, javascript, asp, prolog, vb, c++, vb.Net, C#
300
301 Now I'm focused on .Net development, both windows and web with two-three year experience on both and fully up-to date with 2.0 .Net in both Vb and C#
302 Also have experience with SQL server 2005 and Business Intelligence.
303
304 Jose Luis Lives in Barcelona, Spain, with his cat Pancho. To contact Jose Luis, email him at
305 joslat@gmail.com.
306
307
308 Click here to view Jose Luis Latorre's online profile.
309
2 Real Multi-threading in .NET 2.0
3 remex1980 翻译于 2007-5-16 20:43:21
4 原作者: Jose Luis Latorre
5 原文地址:http://www.codeproject.com/useritems/RealMultiThreading.asp
6
7
8 多线程实例源代码(保留原文处链接)
9 http://www.codeproject.com/useritems/RealMultiThreading/RealMultiThreading_src.zip
10
11
12
13
14
15 简介
16
17 多线程总是那么让人振奋。大家都希望能够同时处理很多事情,不过如果我们没有正确的硬件的话,我们很难达到这点。到目前为止,我们所做的只是分开CPU使用较多的工作,使其为后台进程,这样可以使得界面上不被阻塞。
18
19 不过我希望能够得到更好的效果,并充分利用当前最新的多CPU效能。因此,我将写一个真正的多线程实例,将会有多个线程作为后台线程在运行。
20
21 这就是这篇文章将要写的,不得不说的是,最终的结果实在是让我很激动。希望你也能够发觉它的用处。
22
23 在有4个CPU的多CPU服务器上,我得到了280%的效果(测试的是CPU型的任务),在一些非CPU占用较多的任务中,它可以提高到500% 到1000%的性能。
24
25 背景
26
27 网上也有不少介绍.Net 2.0下的多线程的文章,应该说,我从它们中受益颇多。我正在使用的是BackgroundWorker .Net 2.0组件(不过也有实现在.net 1.1下的代码)。
28
29 这里,我列出一些有用的文章链接:
30 来自Paul Kimmel的很好的介绍性文章 http://www.informit.com/articles/article.asp?p=459619&seqNum=5&rl=1
31 来自Juval Löwy的介绍性文章 http://www.devx.com/codemag/Article/20639/1954?pf=true
32 (必看)Joseph Albahari的C#中使用线程 http://www.albahari.com/threading/part3.html
33 Michael Weinhardt写的在Windows Forms 2.0中一个简单安全的多线程,我使用了这个网页中的CPU密集型任务,这是他从Chris Sell的文章中引用的。
34 http://www.mikedub.net/mikeDubSamples/SafeReallySimpleMultithreadingInWindowsForms20/SafeReallySimpleMultithreadingInWindowsForms20.htm
35
36 如果你对多线程世界仍然不是特别熟悉或者希望了解最新的.Net 2.0的 BackgroundWorker组件,那么应该好好读读上面的文章。
37
38
39
40 提出的问题
41
42 任何一个任务……无论是CPU密集型还是普通的任务:
43
44 CPU密集型:它可以分成一个、两个或多个线程,每个线程会占用一个CPU(这样就使得程序的性能翻番)
45
46 普通任务:每一个顺序执行的普通任务,在进行数据存储或使用一个web service的时候都会有一些延迟。所有的这些,都意味着这些没有使用的时间对于用户或任务本身来说有了浪费。这些时间将被重新安排,并将被并行的任务使用,不会再丢失。也就是说,如果有100个100ms延迟的任务,它们在单线程模型和20个线程模型的性能差距会达到1000%。
47
48
49 我们说,如果要处理一个创建一个网站多个块的任务,不是顺序的执行,而是花1-4秒钟把所有的section创建好;商标,在线用户,最新文章,投票工具等等…… 如果我们能够异步地创建它们,然后在发送给用户,会怎么样?我们就会节省很多webservice的调用,数据库的调用,许多宝贵的时间……这些调用会更快地执行。看上去是不是很诱人?
50
51
52
53 解决方案如下:
54
55 调用BackgroundWorker,正如我们想要的那样,我们会继承它。后台worker会帮助我们建立一个“Worker”,用于异步地做一个工作。
56
57 我们想做的是建立一个工厂Factory(只是为了面向对象的设计,于设计模式无关),任务会放在在这个Factory中执行。这意味着,我们将有一类的任务,一些进程,一些知道如何执行任务的worker。
58
59 当然我们需要一个负责分配任务给这些worker的manager,告诉这些worker当它们做完一步或全部时,做什么事情。当然,我们也需要manager能够告诉worker停止当前的任务。它们也需要休息啊:)当manager说停止的时候,它们就应该停止。
60
61 我们将会从底至上地解释这些,首先从Worker说起,然后再继续Manager。
62
63 Worker
64
65
66 它是Background worker的继承类,我们构建一个构造函数,并分配两个BackgroundWorker的属性,分别是WorkerReportsProgress 和WorkerSupportsCancellation,它们的功能就向其名字的意义一样:报告进度,停止任务。每个Worker还有一个id,Manager将会通过这个id控制它们。
67
68
69 public class MTWorker : BackgroundWorker
70 {
71 #region Private members
72 private int _idxLWorker = 0;
73 #endregion
74
75 #region Properties
76 public int IdxLWorker
77 {
78 get { return _idxLWorker; }
79 set { _idxLWorker = value; }
80 }
81 #endregion
82
83 #region Constructor
84 public MTWorker()
85 {
86 WorkerReportsProgress = true;
87 WorkerSupportsCancellation = true;
88 }
89 public MTWorker(int idxWorker)
90 : this()
91 {
92 _idxLWorker = idxWorker;
93 }
94 #endregion
95
96
97 另外,我们将重载BackgroundWorker的一些函数。事实上,最有意思的是,究竟谁在做真正的工作?它就是OnDoWork,当我们invoke或者启动多线程的时候,它就会被调用。在这里,我们启动任务、执行任务、取消和完成这个任务。
98 我加了两个可能的任务,一个是普通型的,它会申请并等待文件系统、网络、数据库或Webservices的调用。另一个是CPU密集型的任务:计算PI值。你可以试试增加或减少线程数量后,增加或是减少的延迟(我的意思是增减Worker的数量)
99
100
101
102 OnDoWork方法的代码
103
104
105 protected override void OnDoWork(DoWorkEventArgs e)
106 {
107 //Here we receive the necessary data for doing the work
108 //we get an int but it could be a struct, class, whatever..
109 int digits = (int)e.Argument;
110 double tmpProgress = 0;
111 int Progress = 0;
112 String pi = "3";
113
114 // This method will run on a thread other than the UI thread.
115 // Be sure not to manipulate any Windows Forms controls created
116 // on the UI thread from this method.
117 this.ReportProgress(0, pi);
118 //Here we tell the manager that we start the job..
119
120 Boolean bJobFinished = false;
121 int percentCompleteCalc = 0;
122 String TypeOfProcess = "NORMAL"; //Change to "PI" for a cpu intensive task
123 //Initialize calculations
124 while (!bJobFinished)
125 {
126 if (TypeOfProcess == "NORMAL")
127 {
128 #region Normal Process simulation, putting a time
129 delay to emulate a wait-for-something
130 while (!bJobFinished)
131 {
132 if (CancellationPending)
133 {
134 e.Cancel = true;
135 return; //break
136 }
137 //Perform another calculation step
138 Thread.Sleep(250);
139 percentCompleteCalc = percentCompleteCalc + 10;
140 if (percentCompleteCalc >= 100)
141 bJobFinished = true;
142 else
143 ReportProgress(percentCompleteCalc, pi);
144 }
145 #endregion
146 }
147 else
148 {
149 #region Pi Calculation - CPU intensive job,
150 beware of it if not using threading ;) !!
151 //PI Calculation
152 if (digits > 0)
153 {
154 pi += ".";
155 for (int i = 0; i < digits; i += 9)
156 {
157 // Work out pi. Scientific bit :-)
158 int nineDigits = NineDigitsOfPi.StartingAt(i + 1);
159 int digitCount = System.Math.Min(digits - i, 9);
160 string ds = System.String.Format("{0:D9}", nineDigits);
161 pi += ds.Substring(0, digitCount);
162
163 // Show progress
164 tmpProgress = (i + digitCount);
165 tmpProgress = (tmpProgress / digits);
166 tmpProgress = tmpProgress * 100;
167 Progress = Convert.ToInt32(tmpProgress);
168 ReportProgress(Progress, pi);
169 // Deal with possible cancellation
170 if (CancellationPending) //If the manager says to stop, do so..
171 {
172 bJobFinished = true;
173 e.Cancel = true;
174 return;
175 }
176 }
177 }
178 bJobFinished = true;
179 #endregion
180 }
181
182 }
183 ReportProgress(100, pi); //Last job report to the manager ;)
184 e.Result = pi; //Here we pass the final result of the Job
185 }
186 Manager
187
188 这是一个很有趣的地方,我确信它有很大的改进空间-欢迎任何的评论和改进!它所做的是给每个线程生成和配置一个Worker,然后给这些Worker安排任务。目前,传给Worker的参数是数字,但是它能够传送一个包含任务定义的类或结构。一个可能的改进是选择如何做这些内部工作的策略模式。
189
190 调用InitManager方法配置任务,和它的数量等属性。然后,创建一个多线程Worker的数组,配置它们。
191 配置的代码如下:
192
193
194 private void ConfigureWorker(MTWorker MTW)
195 {
196 //We associate the events of the worker
197 MTW.ProgressChanged += MTWorker_ProgressChanged;
198 MTW.RunWorkerCompleted += MTWorker_RunWorkerCompleted;
199 }
200
201 Like this, the Worker’s subclassed thread management Methods are linked to the Methods held by the Manager. Note that with a Strategy pattern implemented we could assign these to the proper manager for these methods.
202 最主要的方法是AssignWorkers,它会检查所有的Worker,如果发现没有任务的Worker,就分配一个任务给它。直到扫描一遍之后,没有发现任何有任务的Worker,这样就意味这任务结束了。不需要再做别的了!
203
204 代码如下:
205
206 public void AssignWorkers()
207 {
208 Boolean ThereAreWorkersWorking = false;
209 //We check all workers that are not doing a job and assign a new one
210 foreach (MTWorker W in _arrLWorker)
211 {
212 if (W.IsBusy == false)
213 {
214 //If there are still jobs to be done
215 //we assign the job to the free worker
216 if (_iNumJobs > _LastSentThread)
217 {
218 //We control the threads associated to a worker
219 //(not meaning the jobs done) just 4 control.
220 _LastSentThread = _LastSentThread + 1;
221 W.JobId = _LastSentThread; //We assign the job number..
222 W.RunWorkerAsync(_iPiNumbers); //We pass the parameters for the job.
223 ThereAreWorkersWorking = true;
224 //We have at least this worker we just assigned the job working..
225 }
226 }
227 else
228 {
229 ThereAreWorkersWorking = true;
230 }
231 }
232
233 if (ThereAreWorkersWorking == false)
234 {
235 //This means that no worker is working and no job has been assigned.
236 //this means that the full package of jobs has finished
237 //We could do something here
238 Button BtnStart = (Button)FormManager.Controls["btnStart"];
239 Button BtnCancel = (Button)FormManager.Controls["btnCancel"];
240 BtnStart.Enabled = true;
241 BtnCancel.Enabled = false;
242 MessageBox.Show("Hi, I'm the manager to the boss (user): " +
243 "All Jobs have finished, boss!!");
244 }
245 }
246
247 只要有任务完成,这个方法就会被调用。从而,保证所有的任务能够完成。
248
249 我们还通过一个属性链接到Form上,这样我们就能向UI上输出我们想要的任何消息了。当然,你可能想链接到其它的一些类,不过这是最基本最通用的。
250
251 Well… improving it we could get a BackgroundManager for all our application needs..
252
253
254
255 界面
256
257 连接到界面上,并不是最主要的功能。这一部分的代码量非常少,也很简单:在Manager中添加一个引用,并在form的构造函数中配置它。
258 在一个按钮中,执行Manager类的LaunchManagedProcess方法。
259
260
261 private MTManager LM;
262 public Form1()
263 {
264 InitializeComponent();
265 LM = new MTManager(this, 25);
266 LM.InitManager();
267 }
268
269 private void btnStart_Click(object sender, EventArgs e)
270 {
271 btnStart.Enabled = false;
272 btnCancel.Enabled = true;
273 LM.LaunchManagedProcess();
274 }
275
276 private void btnCancel_Click(object sender, EventArgs e)
277 {
278 LM.StopManagedProcess();
279 btnCancel.Enabled = false;
280 btnStart.Enabled = true;
281 }
282
283 (下面的自己看喽:)
284 Trying it!
285 This is the funniest part, changing the properties of how many threads to run simultaneously and how many Jobs to be processed and then try it on different CPU’s… ah, and of course, change the calculation method from a CPU-intensive task to a normal task with a operation delay
286 I would love to know your results and what have you done with this, any feedback would be great!!
287
288 Exercises For You…
289 This is not done! It could be a MultiThreadJob Framework if there is being done the following:
290
291 Implement a Strategy pattern that determines the kind of Worker to produce (with a factory pattern) so we will be able to do different kind of jobs inside the same factory.. what about migrating a database and processing each table in a different way… or integrating systems with this engine…
292 Implement -or extend- the strategy pattern for determining the treatment for the Input data and the result data of the jobs. We could too set-up a factory for getting the classes into a operating environment.
293 Optimize the AssignWorkers engine – I am pretty sure it can be improved.
294 Improve the WorkerManager class in order to be able to attach it to another class instead to only a form.
295 Send me the code! I Would love to hear from you and what have you done.
296
297 About Jose Luis Latorre
298
299 Professional developer since 1991, having developed on multiple systems and languages since then, from Unix, as400, lotus notes, flash, javascript, asp, prolog, vb, c++, vb.Net, C#
300
301 Now I'm focused on .Net development, both windows and web with two-three year experience on both and fully up-to date with 2.0 .Net in both Vb and C#
302 Also have experience with SQL server 2005 and Business Intelligence.
303
304 Jose Luis Lives in Barcelona, Spain, with his cat Pancho. To contact Jose Luis, email him at
305 joslat@gmail.com.
306
307
308 Click here to view Jose Luis Latorre's online profile.
309