C++Builder作为一个高效的C++程序语言,其混合了函数语言和物件导向程序编制语言,并且完美的适用于编程、算法、技术和探索性开发,因此可以在使用的过程当中感受到趣味性和吸引力。
注意,线程对象不允许控制线程堆栈的大小或其安全属性。若需要控制这些,必须使用WindowsAPI的Create Thread()或Begin Thread()函数。TThread类有以下一些属性和方法:
1) 属性:
◆Priority:优先级属性。可以设置线程的优先级。
◆Return Value:返回值属性。当线程介绍时返回给其他线程一个数值。
◆Suspended:挂起属性。可以判断线程是否被挂起。
◆Terminated:结束属性。用来标志是否应该结束线程。
◆ThreadID:标识号属性。在整个系统中线程的标识号。使用Windows API函数时该属性非常有用。
2)方法:
◆Do Terminate:产生一个On Terminate事件,但是不结束线程的执行。
◆Resume:唤醒一个线程继续执行。
◆Suspend:挂起一个线程,要与Resume过程成对使用。
◆Synchronize:由主C++线程调用的一个同步过程。
◆Terminate:将Terminate属性设置为True,中止线程的执行。
◆Wait For:等待线程的中止并返回Return Value属性的数值。
2、协调线程
在编写线程执行时运行的代码时,必须考虑到可能同步执行的其他线程的行为。特别注意,避免两个线程试图同时使用相同的全局对象或变量。另外,一个线程中的代码会依赖其他线程执行任务的结果。
1) 避免同时访问
为避免在访问全局对象或变量时与其他线程发生冲突,可能需要暂停其他线程的执行,直到该线程代码完成操作。
(1)锁定对象。一些对象内置了锁定功能,以防止其他线程使用该对象的实例。例如,画布对象(TCanvas及其派生类)有一种Lock()函数可以防止其他线程访问画布,直到调用Unlock()函数。显然,这种方法只对部分类有效。
(2)使用重要区段。若对象没有提供内置的锁定功能,可使用重要区段。重要区段像门一样,每次只允许一个线程进入,要使用重要区段,需创建TCriticalSection的全局实例。TCriticalSection有两个函数:Acquire()(阻止其他线程执行该区域)及Release()(取消对其他线程的阻止)。
(3)使用多重读、独占写的同步器。当使用重要区段来保护全局内存时,每次只有一个线程可以使用该内存。这种保护可能会超出了需要,特别是有一个经常读但很少写的对象或变量时更是如此。多个线程同时读相同内存但没有线程写内存是没有危险的。
当有一些经常被读,但是很少写的全局变量时,可用TMultiReadExclusiveWriteSynchronizer对象保护它。这个对象和重要区段一样,但它允许多个线程同时读,只要没有线程写即可。每个需要读内存的线程首先要调用Begin Read()函数(确保当前无其他线程写内存),线程完成对保护内存读操作后,要调用End Read()函数。任何线程需要写保护内存必须调用Begin Write()函数(确保当前无其他线程读或写内存),完成对保护内存写操作后,调用End Write()函数。
(4)使用Synchronize函数:Void __fast call Synchronize (TThreadMethod &Method);
其中参数Method为一个不带参数的过程名。在这个不带参数的过程中是一些访问VCL的代码。我们可以在Execute过程中调用Synchronize过程来避免对VCL的并发访问。程序运行期间的具体过程实际上是由Synchronize过程来通知主线程。
然后主线程在适当的时机来执行Synchronize过程的参数列表中的那个不带参数的过程。在多个线程的情况下,主线程将Synchronize过程发过来的通知放到消息队列中,然后逐个地响应这些消息。通过这种机制Synchronize实现了线程之间地同步。
2) 等待其他线程
使用C++Builder若线程必须等待另一线程完成某项任务,可让线程临时中断执行。然后,要么等待另一线程完全执行结束,要么等待另一线程通知完成了该任务。
(1)等待线程执行结束
要等待另一线程执行结束,使用它地Wait For()函数。Wait For函数直到那个线程终止才返回,终止的方式要么完成了其Execute()函数,要么由于一个异常。
(2)等待任务完成。有时,只需要等待线程完成一些操作而不是等待线程执行结束。为此,可使用一个事件对象。事件对象(TEvent)应具有全局范围以便他们能够为所有线程可见。
当一个线程完成一个被其他线程依赖的操作时,调用TEvent::Set Event()函数。Set Event发出一个信号,以便其他线程可以检查并得知操作完成。要关掉信号,则使用Reset Event()函数。
例如,当必须等待若干线程完成其执行而不是单个线程时。因为不知道哪个线程最后完成,使用C++Builder函数时,此时,可通过调用Set Event以在线程结束时累加计数值并在最后一个线程结束时发出信号以指示所有线程结束。
【编辑推荐】