基金项目要保留_论文发表__墨水学术,论文发表,发表论文,职称论文(2)
分类:项目管理论文范文 时间:关注:(1)
权。
例如:
CanversObject.lock;
try
画图
finally
CanversObject.unlock;
end;
使用这个保护机制,保证不论有没有异常,unlock都会被执行否则很可能会发生死锁。在多线程设计的时候,应该很注意发生死锁的问题。
2.3使用Waitfor方法
WaitFor的功能是检查Event的状态是否是Set状态(相当于True),如果是则立即返回,如果不是,则等待它变为Set状态,在等待期间,调用WaitFor的线程处于挂起状态。另外WaitFor有一个参数用于超时设置,如果此参数为0,则不等待,立即返回Event的状态,如果是INFINITE则无限等待,直到Set状态发生,若是一个有限的数值,则等待相应的毫秒数后返回Event的状态。
当Event从Reset状态向Set状态转换时,唤醒其它由于WaitFor这个Event而挂起的线程,这就是它为什么叫Event的原因。所谓“事件”就是指“状态的转换”。通过Event可以在线程间传递这种“状态转换”信息。
Waitfor方法的原型如下:FunctionWaitfor(ConstAstring:string):string;
比如唤醒线程的语句:
thread1.resume;
thread1.waitfor;
thread2.resume;
那么所有的线程都必须等待thread1运行完毕后才能运行,其中包括主线程,可以预想,由于thread1调用了主窗体的Edit控件,那么,在thread1运行中间,Edie1也不会显示。
这就告诉我们,这样的代码是不能作为主线程的一部分的,如果与主窗体连接的线程内等待另一个线程结束,而另一个线程又要等待访问用户界面,就可能是程序陷于死锁。
2.4临界区
临界区(CriticalSection)则是一项共享数据访问保护的技术。它其实也是相当于一个全局的布尔变量。但对它的操作有所不同,它只有两个操作:Enter和Leave,同样可以把它的两个状态当作True和False,分别表示现在是否处于临界区中。这两个操作也是原语,所以它可以用于在多线程应用中保护共享数据,防止访问冲突。
用临界区保护共享数据的方法很简单:在每次要访问共享数据之前调用Enter设置进入临界区标志,然后再操作数据,最后调用Leave离开临界区。它的保护原理是这样的:当一个线程进入临界区后,如果此时另一个线程也要访问这个数据,则它会在调用Enter时,发现已经有线程进入临界区,然后此线程就会被挂起,等待当前在临界区的线程调用Leave离开临界区,当另一个线程完成操作,调用Leave离开后,此线程就会被唤醒,并设置临界区标志,开始操作数据,这样就防止了访问冲突。
再来看前面那个例子:
1.线程A进入临界区(假设数据为3)
2.线程B进入临界区,因为A已经在临界区中,所以B被挂起
3.线程A对数据加一(现在是4)
4.线程A离开临界区,唤醒线程B(现在内存中的数据是4)
5.线程B被唤醒,对数据加一(现在就是5了)
6.线程B离开临界区,现在的数据就是正确的了。
关于临界区的使用,有一点要注意:即数据访问时的异常情况处理。因为如果在数据操作时发生异常,将导致Leave操作没有被执行,结果将使本应被唤醒的线程未被唤醒,可能造成程序的没有响应。所以一般来说,临界区正确的做法:
EnterCriticalSection
Try
//操作临界区数据
Finally
LeaveCriticalSection
End;
最后,CriticalSection是操作系统资源,使用前需要创建,使用完后也需要释放。如TThread类用到的一个全局CriticalSection:TheadLock,是在InitThreadSynchronization和DoneThreadSynchronization中进行创建和释放的,而它们则是在Classes单元的Initialization和Finalization中被调用的。
3总结
因此,在Delphi多线程编程中,对可视VCL的访问要放在Synchronize中,通过消息传递到主线程中,由主线程处理。线程共享数据的访问应该用临界区进行保