转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
Delphi中的线程类--之(5,大结局)         ★★★★

Delphi中的线程类--之(5,大结局)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1520 更新时间:2009/4/23 18:35:45
接着就是真正的调用同步方法了。

如果同步方法中出现异常,将被捕获后存入同步方法数据记录中。

重新进入临界区后,调用SetEvent通知调用线程,同步方法执行完成了(详见前面Synchronize中的WaitForSingleObject调用)。

至此,整个Synchronize的实现介绍完成。

 

最后来说一下WaitFor,它的功能就是等待线程执行结束。其代码如下:

function TThread.WaitFor: LongWord;

var

  H: array[0..1] of THandle;

  WaitResult: Cardinal;

  Msg: TMsg;

begin

  H[0] := FHandle;

  if GetCurrentThreadID = MainThreadID then

  begin

    WaitResult := 0;

    H[1] := SyncEvent;

    repeat

      { This prevents a potential deadlock if the background thread

        does a SendMessage to the foreground thread }

      if WaitResult = WAIT_OBJECT_0 + 2 then

        PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);

      WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);

      CheckThreadError(WaitResult <> WAIT_FAILED);

      if WaitResult = WAIT_OBJECT_0 + 1 then

        CheckSynchronize;

    until WaitResult = WAIT_OBJECT_0;

  end else WaitForSingleObject(H[0], INFINITE);

  CheckThreadError(GetExitCodeThread(H[0], Result));

end;

如果不是在主线程中执行WaitFor的话,很简单,只要调用WaitForSingleObject等待此线程的Handle为Signaled状态即可。

如果是在主线程中执行WaitFor则比较麻烦。首先要在Handle数组中增加一个SyncEvent,然后循环等待,直到线程结束(即MsgWaitForMultipleObjects返回WAIT_OBJECT_0,详见MSDN中关于此API的说明)。

在循环等待中作如下处理:如果有消息发生,则通过PeekMessage取出此消息(但并不把它从消息循环中移除),然后调用MsgWaitForMultipleObjects来等待线程Handle或SyncEvent出现Signaled状态,同时监听消息(QS_SENDMESSAGE参数,详见MSDN中关于此API的说明)。可以把此API当作一个可以同时等待多个Handle的WaitForSingleObject。如果是SyncEvent被SetEvent(返回WAIT_OBJECT_0 + 1),则调用CheckSynchronize处理同步方法。

为什么在主线程中调用WaitFor必须用MsgWaitForMultipleObjects,而不能用WaitForSingleObject等待线程结束呢?因为防止死锁。由于在线程函数Execute中可能调用Synchronize处理同步方法,而同步方法是在主线程中执行的,如果用WaitForSingleObject等待的话,则主线程在这里被挂起,同步方法无法执行,导致线程也被挂起,于是发生死锁。

而改用WaitForMultipleObjects则没有这个问题。首先,它的第三个参数为False,表示只要线程Handle或SyncEvent中只要有一个Signaled即可使主线程被唤醒,至于加上QS_SENDMESSAGE是因为Synchronize是通过消息传到主线程来的,所以还要防止消息被阻塞。这样,当线程中调用Synchronize时,主线程就会被唤醒并处理同步调用,在调用完成后继续进入挂起等待状态,直到线程结束。

 

至此,对线程类TThread的分析可以告一个段落了,对前面的分析作一个总结:

1、  线程类的线程必须按正常的方式结束,即Execute执行结束,所以在其中的代码中必须在适当的地方加入足够多的对Terminated标志的判断,并及时退出。如果必须要“立即”退出,则不能使用线程类,而要改用API或RTL函数。

2、  对可视VCL的访问要放在Synchronize中,通过消息传递到主线程中,由主线程处理。

3、  线程共享数据的访问应该用临界区进行保护(当然用Synchronize也行)。

4、  线程通信可以采用Event进行(当然也可以用Suspend/Resume)。

5、  当在多线程应用中使用多种线程同步方式时,一定要小心防止出现死锁。

6、  等待线程结束要用WaitFor方法。

 

Dec.01-03

(终于续完了)

 

上一页  [1] [2] 


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台