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

我的地盘我做主
该用户从未签到
 |
< >最近在写一个程序用到了多线程,所以对CB下的多线程有一定的学习。
( v. W2 S/ _5 _* g( f& P) L现在把自己的一些心得讲一下。水平有限,写的很粗略,请大家见谅。</P>! J$ a" ]7 N" B! q* [, q) [- G0 k
< >CB相对于VC来说,在CB下写多线程程序是很简单的。不仅是VCL中有TThread这个类。封装了那些关于多线程的WINDOW API。我觉得更方便的是他提供了
7 T m3 p1 }6 c$ J9 `( x! D直接访问主VCL线程中对象的能力。可以很容易的和主线程中的窗体,控件* }/ c' n1 t# [
打交道。和单线程的方式没有太多区别。只是在有多个线程都要访问主线程
; }' l: `) j8 b6 ]中的对象(比如访问同一个窗体上的StringGrid).只要用Thread的Synchronize方法来调用那段访问主VCL线程的代码(具体请看帮助),我们就不用担心访问冲突的问题了。而且对于多线程的同步和互斥,CB也对WINDOW 编程中那些机制进行了封装。比如对临界区CriticalSection封装为TCriticalSection.事件Event封装为TEvent.这些类相当简单好用。7 n0 y+ J8 C; {% t, u! U* ]' K
下面就是我觉得比较重要的几点,供大家参考.</P>6 x* a7 z' R' m8 V; O
< >
2 Y) o" M2 T: x7 {0 P1。TThread的WaitFor方法。是等待一个线程返回。其返回值在这个线程里可以任意设定。以便在该线程返回的时候让调用他的线程知道他的运行情况。
- k+ F2 M. R/ D8 W * p$ j \) H( x$ \
在TThread的 OnTerminate事件中做线程的清除工作。他不是线程运行的一部分。
" E) v H( U9 i% X, }; Y而是主VCL线程的一部分。所以在其中不能访问Thread的局部变量(如 int __thread i)
7 }$ l6 x9 d" {6 {: x) z你可以把清楚代码写在这里,不用管现在在EXCUTE()方法执行到了哪个地方。
1 a* A6 e$ O" H7 ?6 Z这么看起来有点类似于C++里的 finally 块的作用。
, L( y- K% x/ v3 Z
: ~3 n; ^1 l+ p0 E2。TEvent很重要。实现线程的同步。WaitFor(int Timeout)功能类似于 & B9 ?( }% F1 E& x
WINDOW API WaitforSingleObject().返回值包括:
! g+ T" t# F4 o: P0 B) ?其中参数Timeout可以设为INFINITE表示永久等待,但这样,程序很容易死在这里。
4 e0 w+ q" s z/ G
" P& l P/ U! ~wrSignaled 该事件发生(成功返回).
' d* G+ v6 ` PwrTimeout 等待超时. * h' {+ }7 s9 ~" E5 ~
wrAbandoned 在该事件的超时期限到达前,该事件对象已经被毁灭了。.
' i' i& B( S" AwrError 在等待过程中有异常产生,要知道具体产生的错误要查看 TEvent的LastError * l, K0 g/ l9 y
属性。
- X5 k+ M: Y8 w: i! ^( ?; m / k9 P: V% s- V* i$ b
3? TCriticalSection 5 j; n+ f6 r. \0 ?
这个相当于WIN32编程中的临界区。
, G, n5 Z2 L# l# }( l% {1 o在多线程编程中,多个线程需要访问同一个公用变量的时候。 2 ^) x$ Y- y6 A
2 L/ B0 C* u% H0 y% E
来保证访问的正确性。对公用变量访问的代码写在Enter();和Leave()之间。
+ o8 T0 Z- h; @% T比如有个公用变量 Count; 3 b, R @& b; [' p: X9 t
以下代码 : 3 @* h& s+ t0 A
TCriticalSection * pSection=new TCriticalSection(); 9 Z1 O a2 u' d0 l6 P
pSection->Enter(); " S& s1 c& y# O# a- p: S# C4 d' P/ g5 i
Count++;
( @7 M5 o/ T3 g% e$ R+ } pSection->Leave(); ( f3 i# H7 N" h$ R) R8 ~
delete p;
; q& s9 B: w |0 {- ~! b : m% [9 s t, j/ x+ Z
Enter()方法进入临界区,对其中的公用变量加锁。 % B r& \: i5 m
Leave()方法离开临界区,对其中的公用变量解锁。 1 g m5 p9 ?& ~4 N/ k: @
0 }- b$ z8 A( z2 J4 V" r$ |
, ~; d8 I$ s8 S6 J! I% X: \3 O
4.TMultiReadExclusiveWriteSynchronizer . S' ^: P. ?/ b m1 P
用来处理类似于多个生产者和多个消费者的问题。这里的消费者是指 S0 \- [- }6 g5 P k
对公用变量进行读操作的线程。
9 q' l, X U1 C, z) [生产者是对公用变量进行写操作的线程。</P>% k6 I$ G5 A, ~ A3 N2 |2 v' B
< >四个方法。
2 G# M" R+ ^2 h5 u BeginRead+ @8 [* q4 r( k9 c" d
EndRead
2 W) F3 g# G" X. {! i0 I- u这两个方法用于消费者。
5 U, g: i4 Y9 U$ |7 G0 d2 b BeginWrite
3 l" `. `2 }% N1 C2 c EndWrite
) U2 Q$ ~) A3 E这两个方法用于生产者。</P>
" o) s& {1 q- k+ h) O+ V< >使用的时候就是要把这个TMutiReadExclusiveWriteSynchronizer 定义一个全局变量。' y. F7 g' M4 [
然后在其他线程中访问他。</P>& [9 c2 J6 f: _+ N! g2 a2 S
# _4 J% [- }; U- K0 s: w$ ~4 ~< >3 a# J E5 S6 N9 `5 W* |& E9 M
</P> |
zan
|