数学建模社区-数学中国

标题: C++Builder的多线程编程中一些体会 [打印本页]

作者: 韩冰    时间: 2005-1-26 13:17
标题: C++Builder的多线程编程中一些体会
<>最近在写一个程序用到了多线程,所以对CB下的多线程有一定的学习。  u  {  n/ ?3 e2 o; d* V
现在把自己的一些心得讲一下。水平有限,写的很粗略,请大家见谅。</P>: I# Y) k! M# C; ~
<>CB相对于VC来说,在CB下写多线程程序是很简单的。不仅是VCL中有TThread这个类。封装了那些关于多线程的WINDOW API。我觉得更方便的是他提供了
3 ^- t) M3 b) i6 |* y5 w: u直接访问主VCL线程中对象的能力。可以很容易的和主线程中的窗体,控件
0 Y9 W% _% t6 l$ R9 `打交道。和单线程的方式没有太多区别。只是在有多个线程都要访问主线程0 y& P$ e2 L# b: \5 H" T
中的对象(比如访问同一个窗体上的StringGrid).只要用Thread的Synchronize方法来调用那段访问主VCL线程的代码(具体请看帮助),我们就不用担心访问冲突的问题了。而且对于多线程的同步和互斥,CB也对WINDOW 编程中那些机制进行了封装。比如对临界区CriticalSection封装为TCriticalSection.事件Event封装为TEvent.这些类相当简单好用。
9 o0 b& K8 i% X7 s3 D% w* u下面就是我觉得比较重要的几点,供大家参考.</P>
4 K' s9 J! H" f/ G4 A<>7 c; k& p8 C4 o
1。TThread的WaitFor方法。是等待一个线程返回。其返回值在这个线程里可以任意设定。以便在该线程返回的时候让调用他的线程知道他的运行情况。 5 ^' [9 c; T- I, a2 v  T
  + H& [2 y5 g# G7 O1 |$ x
在TThread的 OnTerminate事件中做线程的清除工作。他不是线程运行的一部分。 $ F+ @& @" ~2 t, p& J
而是主VCL线程的一部分。所以在其中不能访问Thread的局部变量(如 int __thread i)
/ H+ u$ d" ~$ a4 {你可以把清楚代码写在这里,不用管现在在EXCUTE()方法执行到了哪个地方。 ! S4 j7 Z, q3 z" g1 c, o
这么看起来有点类似于C++里的 finally 块的作用。
2 K; f+ H2 w8 g3 s  5 s" l! F& t; g. |# q5 m) x
2。TEvent很重要。实现线程的同步。WaitFor(int Timeout)功能类似于
" x% W) d* V7 s% x( m. xWINDOW API WaitforSingleObject().返回值包括:
. P# w! `. m( P其中参数Timeout可以设为INFINITE表示永久等待,但这样,程序很容易死在这里。
. i0 F0 u) [" g   
  J. g$ V# M7 O4 P. t  ~wrSignaled 该事件发生(成功返回). 4 y: ?, H7 P* }1 J" }
wrTimeout 等待超时. & u5 j1 B0 {) H1 c: y0 ^) a
wrAbandoned 在该事件的超时期限到达前,该事件对象已经被毁灭了。. ) D& e1 o. [! W2 L9 S
wrError 在等待过程中有异常产生,要知道具体产生的错误要查看 TEvent的LastError
$ T  w% }6 R2 P! ~5 X属性。 ! P- r$ z  o# ^$ ~2 m' S
  
# J3 ?( P( ^% j4 t) ^3? TCriticalSection ' V2 x9 T' k3 p2 g9 R; V& W9 E
这个相当于WIN32编程中的临界区。 / g2 o9 E* _2 X4 k9 w0 h
在多线程编程中,多个线程需要访问同一个公用变量的时候。 + \! y. x0 p7 q7 K% y! c9 f
  
0 {4 Z. P! x9 s2 s, l) m来保证访问的正确性。对公用变量访问的代码写在Enter();和Leave()之间。   y3 B9 b1 s2 Y0 }: j! H  _
比如有个公用变量 Count;
: g8 H* P2 I7 ~, u8 }3 g4 z. I- E以下代码 :
$ G. y2 [# ~+ T0 f" ~% j3 cTCriticalSection * pSection=new TCriticalSection(); 7 b' [" i8 J* T7 k6 }
   pSection-&gt;Enter();
% X  ]3 O7 U; i( F9 Y  |3 N  Count++;
! I2 j7 _9 ^8 C3 r8 s   pSection-&gt;Leave(); $ m) B  U6 g$ s4 T8 f
delete p; , k' G( e% t: q8 f, z$ n
  
6 }3 b* Q# p0 r+ ?+ REnter()方法进入临界区,对其中的公用变量加锁。
4 @! d2 u( @  {+ J( l" hLeave()方法离开临界区,对其中的公用变量解锁。 0 V  h9 t; H8 d" Y
  ! x" t2 l, U3 a8 g
  
$ [: J% h- ^) O( m. s' o4.TMultiReadExclusiveWriteSynchronizer 4 u# z% C! r0 n3 y8 @7 u
用来处理类似于多个生产者和多个消费者的问题。这里的消费者是指+ j6 C2 ^# a8 q/ Y. o0 L
对公用变量进行读操作的线程。
% t+ Y$ B- r8 @1 D生产者是对公用变量进行写操作的线程。</P>
" u# V9 T0 {* ?* U6 }( a$ m8 _& k1 W<>四个方法。2 _1 j  P0 Q* ^, S! G& S" A/ }
  BeginRead( ?9 m1 j1 ?- K
  EndRead
. V' w( O* p5 F! n5 J这两个方法用于消费者。' _4 _4 K* d* N9 J! q( M! V* Q& j4 H
  BeginWrite
( v% C8 K: v+ [  @' W; d  EndWrite" S, h! R$ G* w& c6 x1 v
这两个方法用于生产者。</P>2 j0 ]2 t9 W+ ]1 H) w- ], X
<>使用的时候就是要把这个TMutiReadExclusiveWriteSynchronizer 定义一个全局变量。
! F, \* l) ~6 ]然后在其他线程中访问他。</P>8 \+ W& J. N7 m! d

  T8 S% S. G+ h" _, P<>
$ |0 P% M3 T" q3 ^  b$ U </P>
作者: zd    时间: 2005-3-24 14:27
能讲清楚点,最好用例子
作者: madio    时间: 2005-3-24 19:53
<>讲的很清楚呀!实际上就是调用TThread这个类的一些方法!在new-〉others-〉Threadobject中可以直接建立多线程对象!</P>
作者: zhuyunxiang    时间: 2005-3-28 15:00
<>最好给例子</P>
作者: dddlincool    时间: 2005-4-15 15:40
ddd
作者: dddlincool    时间: 2005-4-15 15:47
[em03]




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5