我是老温,一名热爱学习的嵌入式工程师关注我,一起变得更加优秀!6 W" g% c% o; E% t$ V
嵌入式软件开发过程中,基本都会用到“延时”,本文分享几种Qt种延时处理方法。* ]" F. c# K; h
一、阻塞型延时
) J5 L" g4 I8 C8 f, o/ J$ r% I+ f# a4 s阻塞的原理就是:在延时期间,本线程的事件循环得不到执行。" R7 F8 t0 a5 j7 B( x& q
1、QThread类的sleep()最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),这几个函数的不良后果就是,GUI会在延时的时间段内失去响应,界面卡死,所以,这三个函数一般用在非GUI线程中。+ y0 h5 D1 v5 b( f7 }6 k
QThread::msleep(50);//阻塞延时50ms2 D6 e$ {) l" |
2、使用定时器:死等void Delay_MSec_Suspend(unsigned int msec)
+ w" `$ x1 w- V( C3 k7 X{ ; E/ w6 F6 e8 ]
QTime _Timer = QTime::currentTime().addMSecs(msec);
" T h4 v% {' P while( QTime::currentTime() 二、非阻塞延时原理无非就是利用事件循环,有两种原理:
9 h, F9 ~/ R5 D4 g1、处理本线程的事件循环在等待中,不断强制进入当前线程的事件循环,这样可以把堵塞的事件都处理掉,从而避免程序卡死
; G) R4 a3 _7 A( b% d& _4 y3 C% M: Lvoid Delay_MSec(unsigned int msec)
+ J w/ v" l1 s8 k2 `- q{: O7 O7 {. m; J# ^ f
QTime _Timer = QTime::currentTime().addMSecs(msec);
& I6 F5 r5 d P8 u while( QTime::currentTime() 2、使用子事件循环创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的
. [: l: F0 F0 G0 j" r/ uvoid Delay_MSec(unsigned int msec)
4 d% d/ e+ f. D% e/ W{4 l) \3 p" \2 f) O1 ~% N o
QEventLoop loop;//定义一个新的事件循环: h$ i: J. i3 e- S) e
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数9 ?$ J2 P9 a( S- c5 U8 y" t
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
7 Y" b9 P% f4 m1 r/ x2 _}3 j3 \, u: W/ e' S& p+ K" b
三、耗时代码的处理假设有这样的应用情景:点击某个button之后,需要读入并处理一幅图像,需要耗时20秒才能处理完。
/ o M' {6 K; d5 L% H. H2 {# m% b在这20s内,GUI会失去效应,界面上的任何元素都无法被点击,这种情况应该怎么办?方法有两种:1、用另一个线程去处理这个耗时任务;2、在耗时任务中,不断地去处理本线程的事件循环,以保证GUI的及时响应。1 O" |( F/ w8 K3 M, d9 `; @/ X" I. f
for(i=0; i for(j=0; j 一般来说,processEvents()不宜被调用的过于频繁,也不宜被调用的不够频繁,过于频繁的话,一方面会使线程的响应更好,但另一方面会导致原本就耗时的任务变得更加耗时;
4 O- Z s8 w- {1 l1 I# t1 p7 c不够频繁的话,显然可能会使GUI线程的响应变差,例如每500ms才被调用一次,那么GUI的事件循环就只能500ms才被处理一次,3 v2 k- R0 j! ~& ? r I9 \
当然,这个问题可以通过设定processEvents()的第二个形参略微得到缓解,更好的做法是,保证被调的周期1 d/ p# }( h; n# J/ W
副作用:(特别注意!); k+ Y5 b- e" a# F& }: y
1、在点击按钮之后,这个20s的耗时任务开始执行,尚未执行完毕时,我们点击了GUI的关闭按钮,那么GUI会立即消失,但是这个耗时任务仍然会在后台执行,直到执行完毕,进程才会退出。解决办法:重写关闭事件,在关闭事件的函数中直接结束进程。* @( A' T( g$ ?: R1 i* m: \
2、在点击按钮之后,这个20s的耗时任务开始执行,执行到第5秒时,我们再次点击了这个按钮,那么QT又会执行一个新的20s任务,这个新任务完成后,又会接着把第一个20s任务从上次被打断的第5秒继续执行。如果这个任务是可重入的,后果仅仅是被执行了两遍,如果任务不可重入,那情况就彻底糟糕了。解决办法:点击按钮后把这个按钮disable掉,执行完再enable。
+ h4 ]! r* {+ a: Z2 F来源地址:9 q' l s4 K# M- ^
https://blog.csdn.net/qq_31073871/article/details/80472347-END-7 j3 M8 [0 }, a: Y( F' u; y) L
往期推荐:点击图片即可跳转阅读9 m# b. t. R0 l
2 ]9 l3 |9 P( z4 [$ Z - P0 D% P V4 c4 J6 w
8 p) Z/ k) K( {# d O$ [ {+ o9 t3 @! T
7 H+ d2 H0 U. q& I* O$ C' ]
pfuhryogd136406127725.jpg
$ f1 @5 o* d0 |9 Y) u% p 1 A( {( Y/ w1 C$ E& q) {/ [; e
嵌入式软件工程师,被深夜的硬件调试击碎了傲慢。
. B7 @$ h* }+ F! A7 C, t
% w8 I* `) b! L4 M# n4 Z2 p( z
/ a/ U1 h9 t0 P8 z% m, d" k 8 @7 d c0 t1 B
: |, p! k) @' X# J0 @' t& j/ m
ptw2vfzkwwa6406127825.jpg
$ g8 F0 l7 _ Y+ a6 w F$ z" A7 ~. C ' u9 D+ v9 L; }6 h' ]2 n
把 DeepSeek-R1 大模型部署到RK3588开发板上,看看运行情况如何?
( s2 S( Y0 o$ G d# t- }
3 O- G+ x! N5 R1 G ; C V/ [( @$ h* n" c' y6 J
. M/ c2 d; j5 |! a9 L
nwcysosucrb6406127926.jpg
! y1 b% \: {2 g 4 c: V) R) K. ~% @8 ]9 c3 M
不久的将来,Rust 会成为主流的嵌入式软件编程语言吗?
! _: O" S! s0 Y- K" E8 N $ c' x0 \+ x1 H
: E' ]$ c) ]. o+ P/ d$ u/ h2 Q+ \# ~, x
6 ]0 `( A( t" |$ u4 T0 J2 E# W- y+ r 我是老温,一名热爱学习的嵌入式工程师
8 m7 Y' l/ G. @7 ~% A+ z关注我,一起变得更加优秀! |