- 在线时间
- 0 小时
- 最后登录
- 2007-9-23
- 注册时间
- 2004-9-10
- 听众数
- 3
- 收听数
- 0
- 能力
- 0 分
- 体力
- 9975 点
- 威望
- 7 点
- 阅读权限
- 150
- 积分
- 4048
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1893
- 主题
- 823
- 精华
- 2
- 分享
- 0
- 好友
- 0

我的地盘我做主
该用户从未签到
 |
< >最近在写一个程序用到了多线程,所以对CB下的多线程有一定的学习。
7 g7 s1 V0 u% U/ h1 n- e+ r, B现在把自己的一些心得讲一下。水平有限,写的很粗略,请大家见谅。</P>/ e/ E$ ~, t4 B4 e6 X( ?
< >CB相对于VC来说,在CB下写多线程程序是很简单的。不仅是VCL中有TThread这个类。封装了那些关于多线程的WINDOW API。我觉得更方便的是他提供了
, g; P7 C/ f% \. B9 s直接访问主VCL线程中对象的能力。可以很容易的和主线程中的窗体,控件! \3 r" w. W8 }% |* ^
打交道。和单线程的方式没有太多区别。只是在有多个线程都要访问主线程% y$ c6 M5 A/ `% W
中的对象(比如访问同一个窗体上的StringGrid).只要用Thread的Synchronize方法来调用那段访问主VCL线程的代码(具体请看帮助),我们就不用担心访问冲突的问题了。而且对于多线程的同步和互斥,CB也对WINDOW 编程中那些机制进行了封装。比如对临界区CriticalSection封装为TCriticalSection.事件Event封装为TEvent.这些类相当简单好用。* `' ^/ |' [ d8 @
下面就是我觉得比较重要的几点,供大家参考.</P>
* q* y" w- k" Q* B# ?< >
1 n, c$ I% T4 z0 r1。TThread的WaitFor方法。是等待一个线程返回。其返回值在这个线程里可以任意设定。以便在该线程返回的时候让调用他的线程知道他的运行情况。
7 f% |/ M6 o. e
+ w8 D% \* C/ T, r在TThread的 OnTerminate事件中做线程的清除工作。他不是线程运行的一部分。
7 g0 c# T. p P! i- B+ `! S而是主VCL线程的一部分。所以在其中不能访问Thread的局部变量(如 int __thread i)
4 A4 T$ ^0 s- B5 N3 u你可以把清楚代码写在这里,不用管现在在EXCUTE()方法执行到了哪个地方。 . b/ F l6 G& h1 {8 ]1 O
这么看起来有点类似于C++里的 finally 块的作用。
" X. I; S w/ C( F
& O: ^" F: H v* H2。TEvent很重要。实现线程的同步。WaitFor(int Timeout)功能类似于
- b# U9 s; C& ~WINDOW API WaitforSingleObject().返回值包括: 3 | k/ N3 c* y5 t+ q7 A3 Z
其中参数Timeout可以设为INFINITE表示永久等待,但这样,程序很容易死在这里。 / c1 g& y5 ^; {* k1 J4 I" {" Z: O& {
6 |6 J6 X$ c5 \( AwrSignaled 该事件发生(成功返回).
5 d$ H) I( o, ?# f$ @* ^2 @wrTimeout 等待超时. 3 a# q4 k% m, b$ Z
wrAbandoned 在该事件的超时期限到达前,该事件对象已经被毁灭了。.
' @6 K6 y* {& iwrError 在等待过程中有异常产生,要知道具体产生的错误要查看 TEvent的LastError 4 }3 c% s# X8 h! ^, k7 o
属性。
j5 ]9 ^9 L" I # n& q0 v: X4 Z$ b9 w6 u
3? TCriticalSection $ f" l7 x4 _: g$ ?" m
这个相当于WIN32编程中的临界区。
7 j3 S4 @( n; e {" F- Q在多线程编程中,多个线程需要访问同一个公用变量的时候。
/ u; o2 H$ ^* \, {
5 C( I2 D4 f6 S" ~4 F0 n- c" A+ c来保证访问的正确性。对公用变量访问的代码写在Enter();和Leave()之间。 ' i8 o+ N# m, t4 h4 W) s+ ~6 e
比如有个公用变量 Count; M) B0 L6 y. `) Z1 x% R, F
以下代码 : 1 U+ j! }# x0 R8 E3 m
TCriticalSection * pSection=new TCriticalSection();
/ | L$ H+ W' K1 I* d! z( } pSection->Enter(); : z% W+ ]/ {, V) L6 n! p7 O
Count++;
7 x! j' w3 J/ q" T" F pSection->Leave(); 5 v( O9 E4 X6 i+ s u
delete p;
1 ^" \& ^/ ?0 l8 @. M , m* E/ `1 U$ o6 b# D) \+ E& r' K
Enter()方法进入临界区,对其中的公用变量加锁。
1 R) f8 N. u$ V' d. a% oLeave()方法离开临界区,对其中的公用变量解锁。 6 }0 v' {1 R8 U! ?9 D4 w
! H% a! r$ Y- T * M% n. h/ T" g) O: R
4.TMultiReadExclusiveWriteSynchronizer
3 E r2 d3 R: Y# C. u& G用来处理类似于多个生产者和多个消费者的问题。这里的消费者是指- E! }& @" a) D' u7 d2 p0 F
对公用变量进行读操作的线程。
3 t5 ^" u0 X: T) F( M2 G生产者是对公用变量进行写操作的线程。</P>
# z9 j& w3 r6 W; {4 k< >四个方法。
( \* X( e" C+ A& Y Y& K2 s BeginRead4 Z, v( {* a( e
EndRead
( }+ v2 q6 h3 w. G1 O这两个方法用于消费者。
& B$ O" X+ ~3 D0 \/ e( Q9 V; i BeginWrite
' n9 P2 J4 I4 _/ R) W7 d EndWrite
8 O0 z# G1 k6 E5 h" R这两个方法用于生产者。</P>" j2 P0 H& ?. R+ G5 I7 {3 [0 o
< >使用的时候就是要把这个TMutiReadExclusiveWriteSynchronizer 定义一个全局变量。
7 g/ g+ \& y6 T8 C9 G2 J然后在其他线程中访问他。</P>$ V8 H$ l/ R1 j9 g: ]
8 H- J3 e- k. b* T: j, G! a< >
7 r+ ~1 x; b) b" C z1 w) s5 H5 y </P> |
zan
|