Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 2980|回复: 4

巨坑!WinCE下面的WaitforSingleObject毛病

[复制链接]

该用户从未签到

发表于 2016-11-6 09:49:17 | 显示全部楼层 |阅读模式
在我的一个项目中,创建了一个A线程,这个线程一直WaitforSingleObject,收到信号后,执行一段程序,然后再执行发送该信号的对象的SetEvent方法,通知其执行完毕,发送方则可能在主线程中,也可能在其他线程中,发送方也在WaitforSingleObject等待A线程的回复信号。就这样的一个简单的流程。我做了一个程序,在主线程中,创建一个Timer,每隔300毫秒向A线程发送一个信号,表示需要执行某段程序,然后等待回复(等待时间是3秒),然后下一个Timer事件继续上面的重复动作,连续测试2-3个小时,开始A线程执行这段程序大约需要50毫秒,到后面越来越慢,一直到超过3秒超时。做了各种尝试,均告失败。最后查下来,这WaitforSingleObject貌似存在某种Bug,会导致应用程序执行效率越来越低下,还会出现意想不到的结果。最后不得不放弃这个方法,改动MSGQueue的办法,就全好了。
回复

使用道具 举报

该用户从未签到

发表于 2017-2-10 23:48:53 | 显示全部楼层

RE: 巨坑!WinCE下面的WaitforSingleObject毛病

确定是WinCE下面的WaitforSingleObject下的bug吗?
在多线程里要用好WaitforSingleObject和SetEvent有些事项是要注意的,因为线程之间的执行顺序是不可预测的,你应该设立了两个事件对象,你怎么保证彼此能协调起来?
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2017-2-15 09:19:23 | 显示全部楼层

RE: 巨坑!WinCE下面的WaitforSingleObject毛病

hawk_e2e 发表于 2017-2-10 23:48
确定是WinCE下面的WaitforSingleObject下的bug吗?
在多线程里要用好WaitforSingleObject和SetEvent有些事 ...

A、B两个线程,A线程WaitforSingleObject---->B线程SetEvent给A线程,然后B线程WaitforSingleEvent---->A线程执行完后SetEvent给B线程,然后A线程继续WaitforSingleObject---->B线程得到A的执行结果。

这很容易模拟,比如B线程是主线程,A是一个TThread,你会发现A线程会越来越慢。。。。。
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2017-2-16 12:34:12 | 显示全部楼层

RE: 巨坑!WinCE下面的WaitforSingleObject毛病

ejiemu 发表于 2017-2-15 09:19
A、B两个线程,A线程WaitforSingleObject---->B线程SetEvent给A线程,然后B线程WaitforSingleEvent---->A ...

没这么简单。  你的处理逻辑大概如下:
B线程:

while(..) do
begin
        SetEvent(EventA) ;//通知线程A
        //或许会做些事情
       
        case WaitforSingleEvent(EventB) of
        ...:
        begin
                ResetEvent(EventB) ;
                //...
        end ;
        end ;
end ;


A线程:
while(..) do
begin
        case WaitforSingleEvent(EventA) of
        ...:
        begin
                ResetEvent(EventA) ;
                //执行任务
                SetEvent(EventB) ;
        end ;
        end ;
end ;

------------------------------------------------------------------------
但线程的执行顺序是不可预测的,所以存在2个可能:
1. 在B线程还没执行到ResetEvent(EventB) ; 之前, A线程已经完成任务执行完SetEvent(EventB) ;
   此时B就要挂起来
2. 同理,在A线程还没执行到ResetEvent(EventA) ; 之前,B线程已经执行完SetEvent(EventA) ;
  此时即使B线程发出了执行任务的信号,一样没得到执行。

或许第2个可能是不存在的,但我只是想告诉你,线程执行的先后并不都象你想那样。
要实现用事件来协调线程的执行有点伤脑,
1. 你要在A和B线程里分别设立变量记录线程的状态
2. 在状态改变和判断上,需要用临界区

------------------------------
除非你在waiforsingleobject前后记录时间确实是函数问题,我想出现这种情况多半是协调没弄好。
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2017-3-30 10:08:25 | 显示全部楼层

RE: 巨坑!WinCE下面的WaitforSingleObject毛病

hawk_e2e 发表于 2017-2-16 12:34
没这么简单。  你的处理逻辑大概如下:
B线程:

原理跟你说的一样,但是不存在ResetEvent这样的写法,我的Event是被触发后自动Reset的,所以理论上来说不会出现你讲的情况。CreateEvent(nil, False, .....).
回复 支持 反对

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-2 10:06 , Processed in 0.032417 second(s), 10 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表