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

我的地盘我做主
该用户从未签到
 |
< >最近在写一个程序用到了多线程,所以对CB下的多线程有一定的学习。
* p k$ {+ X. [% O0 ]9 n6 I4 D4 v现在把自己的一些心得讲一下。水平有限,写的很粗略,请大家见谅。</P>9 t* e3 Y: {; Y* T2 D' d+ C
< >CB相对于VC来说,在CB下写多线程程序是很简单的。不仅是VCL中有TThread这个类。封装了那些关于多线程的WINDOW API。我觉得更方便的是他提供了
2 I k+ b" B I& S- h, j9 z直接访问主VCL线程中对象的能力。可以很容易的和主线程中的窗体,控件" i, e2 f" B/ M" Y; V
打交道。和单线程的方式没有太多区别。只是在有多个线程都要访问主线程
% N: P0 b3 |/ @9 z4 Q" s1 p. R中的对象(比如访问同一个窗体上的StringGrid).只要用Thread的Synchronize方法来调用那段访问主VCL线程的代码(具体请看帮助),我们就不用担心访问冲突的问题了。而且对于多线程的同步和互斥,CB也对WINDOW 编程中那些机制进行了封装。比如对临界区CriticalSection封装为TCriticalSection.事件Event封装为TEvent.这些类相当简单好用。6 `2 B8 b/ {7 T$ h( Z# V
下面就是我觉得比较重要的几点,供大家参考.</P>
w' }! ?% V, Z8 U! }; X0 m< >8 ]) T* d# {3 \! I2 P: D& c
1。TThread的WaitFor方法。是等待一个线程返回。其返回值在这个线程里可以任意设定。以便在该线程返回的时候让调用他的线程知道他的运行情况。 ' I W9 Q! }* L5 B) [6 |
" P4 y3 P" {. s! m7 @在TThread的 OnTerminate事件中做线程的清除工作。他不是线程运行的一部分。
0 Q6 j2 v$ m& t9 p" H; P/ h而是主VCL线程的一部分。所以在其中不能访问Thread的局部变量(如 int __thread i)
+ Y% t( P& G1 v! Y" c- @, k你可以把清楚代码写在这里,不用管现在在EXCUTE()方法执行到了哪个地方。 2 }0 {7 k! I# w+ P5 |1 _
这么看起来有点类似于C++里的 finally 块的作用。
. O V8 A; E5 J" P6 E& x3 l
3 T+ ~, _- d& e2。TEvent很重要。实现线程的同步。WaitFor(int Timeout)功能类似于
6 r) W0 Q. q& b3 w. m8 ~, oWINDOW API WaitforSingleObject().返回值包括: 8 N7 l4 _1 G+ u; w, K
其中参数Timeout可以设为INFINITE表示永久等待,但这样,程序很容易死在这里。 6 ]6 M. i) o5 s8 Y( Q/ E& e' j- v
: k) Z. Y3 t" |: W" v/ o
wrSignaled 该事件发生(成功返回). + p% K2 j" m/ \" w7 w1 S& r! {
wrTimeout 等待超时. : ?. d& U1 A" {2 _; I+ `9 M) j7 ?
wrAbandoned 在该事件的超时期限到达前,该事件对象已经被毁灭了。. 7 {; ]* m: ?3 i# e
wrError 在等待过程中有异常产生,要知道具体产生的错误要查看 TEvent的LastError 8 C. {% t0 @3 s9 s
属性。 , y% b: ?$ ^; _
; u$ p \/ h: ^6 I
3? TCriticalSection
7 {6 I# |9 e( v8 m. [6 M这个相当于WIN32编程中的临界区。
7 x9 y! b1 A$ R5 |在多线程编程中,多个线程需要访问同一个公用变量的时候。 , `' q" q5 S: Y# {$ j
* Y8 M0 F {' W6 D% X: b9 h6 Y来保证访问的正确性。对公用变量访问的代码写在Enter();和Leave()之间。 ' `* h* s, o: Z
比如有个公用变量 Count;
/ ]0 A1 d8 h; @以下代码 :
) S+ T6 @. y, q0 c& S5 kTCriticalSection * pSection=new TCriticalSection(); 6 ?! m1 `5 M, v
pSection->Enter();
5 y- j5 N8 d+ P1 p Count++; ) \6 } ~! t* |' I6 K6 }# L9 M- _
pSection->Leave(); 9 i5 F" R" q0 N* t2 z
delete p;
# M# ?2 {+ C& [/ F2 n! E. k
7 }4 t. a( K: N2 LEnter()方法进入临界区,对其中的公用变量加锁。 * i; }/ S, _; r2 p1 P3 X: Y3 d% K* h
Leave()方法离开临界区,对其中的公用变量解锁。 4 E. N/ W$ ]5 K! r
6 {. Q" \; q' i0 R- P9 ^* ~
) k, x4 V2 h0 c+ \* H4.TMultiReadExclusiveWriteSynchronizer
& r% \$ o! @. Z4 K5 \( b' ~4 q! ^用来处理类似于多个生产者和多个消费者的问题。这里的消费者是指, o4 l: r2 `# |) a' I. `' I( j
对公用变量进行读操作的线程。# C) `6 @1 {6 W1 Y
生产者是对公用变量进行写操作的线程。</P>9 j" V0 I, |6 S) Y. Z7 |
< >四个方法。& x, Q" ?0 g8 X5 b: |
BeginRead5 T ?! M9 @" g5 A7 H* Z( P/ [
EndRead
# A; {' a9 B: W8 Y8 w! C7 R这两个方法用于消费者。! L2 J: L. c- I, A% v: N
BeginWrite
1 ~: r c, |3 f: M EndWrite9 g) B' k' ~, w' ~+ i4 n
这两个方法用于生产者。</P>
7 `, ]6 m I+ M% u6 D% _< >使用的时候就是要把这个TMutiReadExclusiveWriteSynchronizer 定义一个全局变量。7 i1 s2 [& s( G2 I1 s6 `
然后在其他线程中访问他。</P>3 n) @7 R3 _6 e5 G# N1 {4 s6 @
- g5 O" `5 R* L( c6 X! U8 C% j9 x
< >
% H8 p# m4 h. S' k; }% q" y </P> |
zan
|