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

我的地盘我做主
该用户从未签到
 |
< >最近在写一个程序用到了多线程,所以对CB下的多线程有一定的学习。 {. I; p/ m7 N
现在把自己的一些心得讲一下。水平有限,写的很粗略,请大家见谅。</P>: ^ t6 ]/ B! K% u
< >CB相对于VC来说,在CB下写多线程程序是很简单的。不仅是VCL中有TThread这个类。封装了那些关于多线程的WINDOW API。我觉得更方便的是他提供了) W" M6 U- ~8 Z( r5 W% C3 G' ^
直接访问主VCL线程中对象的能力。可以很容易的和主线程中的窗体,控件3 ]- t, m1 v$ T/ q: X
打交道。和单线程的方式没有太多区别。只是在有多个线程都要访问主线程
' P# L2 M1 G/ E6 A: @* t中的对象(比如访问同一个窗体上的StringGrid).只要用Thread的Synchronize方法来调用那段访问主VCL线程的代码(具体请看帮助),我们就不用担心访问冲突的问题了。而且对于多线程的同步和互斥,CB也对WINDOW 编程中那些机制进行了封装。比如对临界区CriticalSection封装为TCriticalSection.事件Event封装为TEvent.这些类相当简单好用。9 g9 f* s. ~4 h# N* l
下面就是我觉得比较重要的几点,供大家参考.</P>, o, @6 V9 H0 w
< >
2 w4 L; A! Z: j# x5 [1。TThread的WaitFor方法。是等待一个线程返回。其返回值在这个线程里可以任意设定。以便在该线程返回的时候让调用他的线程知道他的运行情况。
* e- I% b% R+ ~/ e/ h8 R, r* f, k
. a. K; f A; Y( ?0 N0 N在TThread的 OnTerminate事件中做线程的清除工作。他不是线程运行的一部分。 + I' }, S/ ?' D
而是主VCL线程的一部分。所以在其中不能访问Thread的局部变量(如 int __thread i)
' c+ `# [- z3 V你可以把清楚代码写在这里,不用管现在在EXCUTE()方法执行到了哪个地方。
: @, T2 t3 i: i; b- \4 i这么看起来有点类似于C++里的 finally 块的作用。 4 t5 E1 i) @5 C3 y$ F
$ ^$ a' i, W) ^, ?) E) L# H8 Z
2。TEvent很重要。实现线程的同步。WaitFor(int Timeout)功能类似于 6 y- M1 `& Z$ q
WINDOW API WaitforSingleObject().返回值包括: # {& u( P/ e; ~, Y$ k/ h) P [
其中参数Timeout可以设为INFINITE表示永久等待,但这样,程序很容易死在这里。 6 k' A* Z+ t$ D2 d* q% I2 u
* s6 N& V2 e8 i) [& _: p0 lwrSignaled 该事件发生(成功返回).
4 ~" }3 A/ `2 |$ ]wrTimeout 等待超时. ; ^% T' n1 Y* Q5 l: h: R' H. S
wrAbandoned 在该事件的超时期限到达前,该事件对象已经被毁灭了。. 9 L! g% P" C; [0 _
wrError 在等待过程中有异常产生,要知道具体产生的错误要查看 TEvent的LastError 3 c; `, |: m/ H- K4 z n6 ?* Z
属性。
1 x$ d$ [- I2 t( O
; Z6 I, `. w" } L3? TCriticalSection
. k5 a' `% p5 }! ]6 m# D这个相当于WIN32编程中的临界区。
7 d/ y! }0 e4 l- q6 K" V3 v6 |, {在多线程编程中,多个线程需要访问同一个公用变量的时候。
: H/ I y( L3 D. O: U
) ] V9 |1 k2 X3 S来保证访问的正确性。对公用变量访问的代码写在Enter();和Leave()之间。
7 N% |7 _: M( H0 r比如有个公用变量 Count;
2 x6 F5 b" G, s2 k, @) Z5 A以下代码 :
: |4 x/ n! ]- W* I0 Z4 Z# A; M2 ZTCriticalSection * pSection=new TCriticalSection();
7 ~7 x* S8 B; w pSection->Enter();
3 ^2 n/ O* |5 X; b% p- Y+ n; [( ? Count++; 8 p2 Z' Q% Z" u2 _2 O3 J* {
pSection->Leave(); " m5 A1 {9 A, w j
delete p;
7 P! k& y. ]" h
* O! v, ^- {6 S5 cEnter()方法进入临界区,对其中的公用变量加锁。 # A# W% V8 s& i: |" Y
Leave()方法离开临界区,对其中的公用变量解锁。
& Z( z* ^0 c- e+ e3 l+ Z/ W ]$ u' {3 C5 M; V
5 d& ]+ [9 g: \) Z+ b" Q. w' {9 O# Y/ a4.TMultiReadExclusiveWriteSynchronizer 0 E" K/ m7 L t- f" C
用来处理类似于多个生产者和多个消费者的问题。这里的消费者是指
2 o" h! S ?! n" @对公用变量进行读操作的线程。
/ ]/ {+ c! A0 Y# i+ n+ G( q1 T生产者是对公用变量进行写操作的线程。</P># w, l3 O; ]) b) x! D! M0 v* {& N6 |: ]
< >四个方法。' `8 o' ?( x- l& p- J- }
BeginRead
$ P. m& b2 y" I% H* U5 Y/ {/ G EndRead, A( N3 w. M! O& x
这两个方法用于消费者。
' T5 u, h }- p+ k& | BeginWrite
1 F1 d' ~; u v$ X$ V EndWrite
: P- L2 J ?2 j! T$ L这两个方法用于生产者。</P>
9 P+ g4 h* n" v5 _1 ~$ s: E" K/ @, F< >使用的时候就是要把这个TMutiReadExclusiveWriteSynchronizer 定义一个全局变量。; a1 K( [2 e, P2 J) Z5 P" M0 @
然后在其他线程中访问他。</P>
8 K) L N2 H6 {9 F+ c0 k1 P# T; P
" v0 U) C: v3 o' F< >2 X5 I% c& G8 S# [5 e
</P> |
zan
|