【MFC】【线程&消息】关于窗口的OnPaint()与缩放OnTimer()同时进行.(相机采集状态下)

VergilYe 图像算法工程师  2017-11-10 10:26:44
目前我的需求是:
1.一个相机处于采集状态下,(在线程中采集,在窗口上显示) 帧率约10fps.
2.采集时,窗口可以进行缩放(长按按钮,使用OnTimer) 130ms一次

目前这两个功能都已经实现了,单独进行是完全没有问题的.
但是我发现相机采集中,同时进行缩放,OnTimer会发生堵塞.

另外,我发现在采集状态下,其他系统消息的响应也会特别慢.
(例如左上角的"菜单"按钮,点击后,展开很缓慢)
(例如Button的Tip提示也会显示缓慢)

请教一下大神,如下问题
该如何去定位这个问题,只是单纯WM_PAINT和WM_TIMER的消息堵塞?还是其他问题造成的?
该如何解决这种问题?
是不是我实现需求的方式有问题,才导致消息堵塞的?
要实现我的需求,有什么需要注意的地方?
有没有更好的方式去实现?

欢迎大家来讨论讨论~
非常感谢!
...全文
670 35 点赞 打赏 收藏 举报
写回复
35 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
VergilYe 2017-12-04
我暂时将采集和OnTimer分开了,使用OnTimer时,暂停采集.. 没办法,只能先这样做了.. 结贴了.
  • 打赏
  • 举报
回复
叶恭介1989 2017-11-30
主线程取出速度慢的话,那就只拿保存缓存CDC数组的最后一个显示,或者倒数第几个显示就行了,数组前面的丢掉,因为显示速度这么快,缺几帧画面不影响,关键是不要卡主界面
  • 打赏
  • 举报
回复
赵4老师 2017-11-30
Coordinate Space and Transformation Functions The following functions are used with coordinate spaces and transformations. ClientToScreen CombineTransform DPtoLP GetCurrentPositionEx GetGraphicsMode GetMapMode GetViewportExtEx GetViewportOrgEx GetWindowExtEx GetWindowOrgEx GetWorldTransform LPtoDP MapWindowPoints ModifyWorldTransform OffsetViewportOrgEx OffsetWindowOrgEx ScaleViewportExtEx ScaleWindowExtEx ScreenToClient SetGraphicsMode SetMapMode SetViewportExtEx SetViewportOrgEx SetWindowExtEx SetWindowOrgEx SetWorldTransform
  • 打赏
  • 举报
回复
VergilYe 2017-11-30
引用 29 楼 zhao4zhong1 的回复:
[quote=引用 28 楼 VergilYe 的回复:] [quote=引用 27 楼 Greg_han 的回复:] 界面消息队列是有消息限制的,太多消息就容易阻塞它,导致处理变慢
请问,应该如何去防止这种状况出现? 有具体的实例可以参考一下吗?[/quote] 避免不必要的界面绘制。 比如 绘制不在显示范围的内容 绘制没有改变的内容 绘制变化速度超过人眼可辨识能力 …… [/quote] 赵老师你好,我想再请教一下: 1.绘制不在显示范围的内容 我目前是相当于一张画布放在一个带有滚动条的窗口里面.那么画布超过窗口的部分,会不会也自动刷新? 2.绘制没有改变的内容 这个我有听说过脏矩形技术,可是却不知道如何判断没有改变的内容有哪些? 另外,我有尝试过,模拟脏矩形刷新,发现矩形里面与外面的衔接不太好...而且MFC里的坐标都是用CPoint储存的,并不够精确啊.. 谢谢!
  • 打赏
  • 举报
回复
VergilYe 2017-11-30
引用 30 楼 cvbtvbwu 的回复:
[quote=引用 26 楼 VergilYe 的回复:] [quote=引用 24 楼 cvbtvbwu 的回复:] 照片一直刷新,用双缓冲没意义。 费时间的操作不要放在OnPaint里,线程那里采集后可以同时写入缓存CDC之后加入集合数组。主线程定时取出来显示就行了。
目前,OnPaint耗时最多也就40ms,属于可接受范围. 但是,按照我的理解: 当我把缓存DC加入集合数组, 假如主线程取出的速度比采集的速度慢,那么主线程采集出来的图片不就一直处于延时的状态么?而且时间越往后,延时就越大?
引用 25 楼 worldy 的回复:
建议: 主界面和图片采集使用不同的线程 在同一个线程中,WM_TIMER的优先级低,只有线程里没有更高优先级的消息,才处理WM_TIMER
目前就是这样做的.但是还是会堵塞....为何会发生这样的状况...[/quote] 主线程取出的速度怎么会比采集的速度慢呢,采集要采集数据和缓存进CDC里,主线程只是拿出来copy CDC,主线程肯定快[/quote] 如果主线程只是显示相机采集的数据的话,肯定是主线程快....可是我在OnPaint里面还有一些自绘的ROI,加上一些数据显示,再加上一些网格显示..这就不一定是主线程比较快了... 另外,假设主线程取出速度一定比采集速度快,那么建立数组的意义不就没有了吗.. 还是不太明白..
  • 打赏
  • 举报
回复
叶恭介1989 2017-11-28
引用 26 楼 VergilYe 的回复:
[quote=引用 24 楼 cvbtvbwu 的回复:] 照片一直刷新,用双缓冲没意义。 费时间的操作不要放在OnPaint里,线程那里采集后可以同时写入缓存CDC之后加入集合数组。主线程定时取出来显示就行了。
目前,OnPaint耗时最多也就40ms,属于可接受范围. 但是,按照我的理解: 当我把缓存DC加入集合数组, 假如主线程取出的速度比采集的速度慢,那么主线程采集出来的图片不就一直处于延时的状态么?而且时间越往后,延时就越大?
引用 25 楼 worldy 的回复:
建议: 主界面和图片采集使用不同的线程 在同一个线程中,WM_TIMER的优先级低,只有线程里没有更高优先级的消息,才处理WM_TIMER
目前就是这样做的.但是还是会堵塞....为何会发生这样的状况...[/quote] 主线程取出的速度怎么会比采集的速度慢呢,采集要采集数据和缓存进CDC里,主线程只是拿出来copy CDC,主线程肯定快
  • 打赏
  • 举报
回复
VergilYe 2017-11-28
引用 27 楼 Greg_han 的回复:
界面消息队列是有消息限制的,太多消息就容易阻塞它,导致处理变慢
请问,应该如何去防止这种状况出现? 有具体的实例可以参考一下吗?
  • 打赏
  • 举报
回复
赵4老师 2017-11-28
引用 28 楼 VergilYe 的回复:
[quote=引用 27 楼 Greg_han 的回复:] 界面消息队列是有消息限制的,太多消息就容易阻塞它,导致处理变慢
请问,应该如何去防止这种状况出现? 有具体的实例可以参考一下吗?[/quote] 避免不必要的界面绘制。 比如 绘制不在显示范围的内容 绘制没有改变的内容 绘制变化速度超过人眼可辨识能力 ……
  • 打赏
  • 举报
回复
Greg_han 2017-11-27
界面消息队列是有消息限制的,太多消息就容易阻塞它,导致处理变慢
  • 打赏
  • 举报
回复
VergilYe 2017-11-27
引用 24 楼 cvbtvbwu 的回复:
照片一直刷新,用双缓冲没意义。 费时间的操作不要放在OnPaint里,线程那里采集后可以同时写入缓存CDC之后加入集合数组。主线程定时取出来显示就行了。
目前,OnPaint耗时最多也就40ms,属于可接受范围. 但是,按照我的理解: 当我把缓存DC加入集合数组, 假如主线程取出的速度比采集的速度慢,那么主线程采集出来的图片不就一直处于延时的状态么?而且时间越往后,延时就越大?
引用 25 楼 worldy 的回复:
建议: 主界面和图片采集使用不同的线程 在同一个线程中,WM_TIMER的优先级低,只有线程里没有更高优先级的消息,才处理WM_TIMER
目前就是这样做的.但是还是会堵塞....为何会发生这样的状况...
  • 打赏
  • 举报
回复
worldy 2017-11-23
建议: 主界面和图片采集使用不同的线程 在同一个线程中,WM_TIMER的优先级低,只有线程里没有更高优先级的消息,才处理WM_TIMER
  • 打赏
  • 举报
回复
叶恭介1989 2017-11-23
照片一直刷新,用双缓冲没意义。 费时间的操作不要放在OnPaint里,线程那里采集后可以同时写入缓存CDC之后加入集合数组。主线程定时取出来显示就行了。
  • 打赏
  • 举报
回复
VergilYe 2017-11-23
引用 22 楼 jszj 的回复:
[quote=引用 20 楼 VergilYe 的回复:] [quote=引用 19 楼 jszj 的回复:] [quote=引用 16 楼 VergilYe 的回复:] [quote=引用 15 楼 jszj 的回复:] 堵塞应该是timer导致。 timer是windows的一个消息,当这个消息没有处理完时,则其它的消息应该是不会被处理,所以在timer里采集图像的过程缓慢导致整个消息循环慢起来。 建议建立一个单独的线程进行图像采集显示的话可以定时40ms刷新一次就差不多了
但是,我不用Timer,只是在采集状态下,点击左上角菜单,结果连菜单也弹不出来.... 可以看出这是采集造成的堵塞.[/quote] 是在线程里采集吗?采集后有显示吗?线程采集有Sleep吗? 可以注意一下cpu占用[/quote] 是在线程里采集,采集成功后,发消息进行画面刷新. 线程中没有Sleep,加上Sleep的话,帧率就降低了.. CPU占用,约25%,[/quote] “CPU占用,约25%”,是几核的?如果是4核的,那相当于它占用了100%的CPU了。 “发消息进行画面刷新”,是如何发的?用SendMessage还是PostMessage?如果是用SendMessage肯定效果不好。 如果想较为彻底地解决,建议采集和刷新分开: 1. 目前的采集线程保留,把采集到的数据放到一个变量中A,A在要显示的类中声明,即范围为显示类内可见。注意在循环过程中加Sleep,防止占满CPU 2. 在OnTimer中把A显示出来。定时器间隔40ms即可,不需要太精确 [/quote] 抱歉,最近有点忙,没有及时回答你的问题. 确实是4核.占用了单核的100%. 采集和刷新是分开的,用PostMessage发送消息:更新缓存DC.所以,采集和刷新其实并不是同步的 1.目前正是把采集数据放到缓存DC,然后再刷新的. 2. 这个方法,应该会出现这种状况:(猜想) 缓存DC正在更新时(但是没更新完毕),OnTimer进行显示,然后出现画面撕裂感?
  • 打赏
  • 举报
回复
red-fly 2017-11-18
引用 20 楼 VergilYe 的回复:
[quote=引用 19 楼 jszj 的回复:] [quote=引用 16 楼 VergilYe 的回复:] [quote=引用 15 楼 jszj 的回复:] 堵塞应该是timer导致。 timer是windows的一个消息,当这个消息没有处理完时,则其它的消息应该是不会被处理,所以在timer里采集图像的过程缓慢导致整个消息循环慢起来。 建议建立一个单独的线程进行图像采集显示的话可以定时40ms刷新一次就差不多了
但是,我不用Timer,只是在采集状态下,点击左上角菜单,结果连菜单也弹不出来.... 可以看出这是采集造成的堵塞.[/quote] 是在线程里采集吗?采集后有显示吗?线程采集有Sleep吗? 可以注意一下cpu占用[/quote] 是在线程里采集,采集成功后,发消息进行画面刷新. 线程中没有Sleep,加上Sleep的话,帧率就降低了.. CPU占用,约25%,[/quote] “CPU占用,约25%”,是几核的?如果是4核的,那相当于它占用了100%的CPU了。 “发消息进行画面刷新”,是如何发的?用SendMessage还是PostMessage?如果是用SendMessage肯定效果不好。 如果想较为彻底地解决,建议采集和刷新分开: 1. 目前的采集线程保留,把采集到的数据放到一个变量中A,A在要显示的类中声明,即范围为显示类内可见。注意在循环过程中加Sleep,防止占满CPU 2. 在OnTimer中把A显示出来。定时器间隔40ms即可,不需要太精确
  • 打赏
  • 举报
回复
VergilYe 2017-11-17
目前我的做法是缩放时停止采集,缩放完成继续采集. 但是这只能勉强解决OnTimer的问题. 系统菜单打不开,Button Tip显示缓慢,这些都还是存在.
  • 打赏
  • 举报
回复
VergilYe 2017-11-17
引用 19 楼 jszj 的回复:
[quote=引用 16 楼 VergilYe 的回复:] [quote=引用 15 楼 jszj 的回复:] 堵塞应该是timer导致。 timer是windows的一个消息,当这个消息没有处理完时,则其它的消息应该是不会被处理,所以在timer里采集图像的过程缓慢导致整个消息循环慢起来。 建议建立一个单独的线程进行图像采集显示的话可以定时40ms刷新一次就差不多了
但是,我不用Timer,只是在采集状态下,点击左上角菜单,结果连菜单也弹不出来.... 可以看出这是采集造成的堵塞.[/quote] 是在线程里采集吗?采集后有显示吗?线程采集有Sleep吗? 可以注意一下cpu占用[/quote] 是在线程里采集,采集成功后,发消息进行画面刷新. 线程中没有Sleep,加上Sleep的话,帧率就降低了.. CPU占用,约25%,
  • 打赏
  • 举报
回复
赵4老师 2017-11-16
Multiple Threads in the User Interface http://msdn.microsoft.com/zh-cn/library/ms810439.aspx
  • 打赏
  • 举报
回复
sichuanwww 2017-11-16
Timer是个坏东西
  • 打赏
  • 举报
回复
red-fly 2017-11-16
引用 16 楼 VergilYe 的回复:
[quote=引用 15 楼 jszj 的回复:] 堵塞应该是timer导致。 timer是windows的一个消息,当这个消息没有处理完时,则其它的消息应该是不会被处理,所以在timer里采集图像的过程缓慢导致整个消息循环慢起来。 建议建立一个单独的线程进行图像采集显示的话可以定时40ms刷新一次就差不多了
但是,我不用Timer,只是在采集状态下,点击左上角菜单,结果连菜单也弹不出来.... 可以看出这是采集造成的堵塞.[/quote] 是在线程里采集吗?采集后有显示吗?线程采集有Sleep吗? 可以注意一下cpu占用
  • 打赏
  • 举报
回复
VergilYe 2017-11-15
引用 15 楼 jszj 的回复:
堵塞应该是timer导致。 timer是windows的一个消息,当这个消息没有处理完时,则其它的消息应该是不会被处理,所以在timer里采集图像的过程缓慢导致整个消息循环慢起来。 建议建立一个单独的线程进行图像采集显示的话可以定时40ms刷新一次就差不多了
但是,我不用Timer,只是在采集状态下,点击左上角菜单,结果连菜单也弹不出来.... 可以看出这是采集造成的堵塞.
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
进程/线程/DLL
加入

1.5w+

社区成员

VC/MFC 进程/线程/DLL
申请成为版主
帖子事件
创建了帖子
2017-11-10 10:26
社区公告
暂无公告