我是老温,一名热爱学习的嵌入式工程师关注我,一起变得更加优秀!4 x% f6 a" a8 X0 J6 z% r
嵌入式软件开发过程中,基本都会用到“延时”,本文分享几种Qt种延时处理方法。
W/ |5 X7 @0 @4 }' M一、阻塞型延时
- t1 M3 o, o) u9 S1 K8 b$ E+ R, F阻塞的原理就是:在延时期间,本线程的事件循环得不到执行。. \6 t' w. M$ N$ {
1、QThread类的sleep()最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),这几个函数的不良后果就是,GUI会在延时的时间段内失去响应,界面卡死,所以,这三个函数一般用在非GUI线程中。
; C" q4 m2 p P7 d+ IQThread::msleep(50);//阻塞延时50ms
3 |8 V1 ]0 y: h' W' O2、使用定时器:死等void Delay_MSec_Suspend(unsigned int msec)
4 o2 g* ~' e& O; M. o. q) M5 P% Q{ . {( u& S# P% C
QTime _Timer = QTime::currentTime().addMSecs(msec);4 d) ?/ A7 h7 C5 t5 A
while( QTime::currentTime() 二、非阻塞延时原理无非就是利用事件循环,有两种原理:0 O. L2 ~8 L) q3 O9 S
1、处理本线程的事件循环在等待中,不断强制进入当前线程的事件循环,这样可以把堵塞的事件都处理掉,从而避免程序卡死. G/ t+ E2 e4 [$ K3 T- f
void Delay_MSec(unsigned int msec)
' o: `) h6 H' D& f* o{
( A) l+ C9 S8 }* X; j QTime _Timer = QTime::currentTime().addMSecs(msec);
v$ ?* Y) W' _+ R+ p while( QTime::currentTime() 2、使用子事件循环创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的
: D' y6 B: x3 W$ M" J; {7 }8 Wvoid Delay_MSec(unsigned int msec)
# S1 Y% I# \* U1 R{# [ h+ W9 e! g/ L% ~/ y
QEventLoop loop;//定义一个新的事件循环0 E7 A7 N* P: }1 h* Y: U
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
' o$ _/ _6 }. A% g' [ loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出1 P6 ]8 E. h' r9 U* V$ J3 E, K. U8 C
}! U7 _2 j' x7 o. [
三、耗时代码的处理假设有这样的应用情景:点击某个button之后,需要读入并处理一幅图像,需要耗时20秒才能处理完。
: d1 Y" J& Q) r: S. ]' N在这20s内,GUI会失去效应,界面上的任何元素都无法被点击,这种情况应该怎么办?方法有两种:1、用另一个线程去处理这个耗时任务;2、在耗时任务中,不断地去处理本线程的事件循环,以保证GUI的及时响应。$ c# ^: d8 g3 W/ |0 i
for(i=0; i for(j=0; j 一般来说,processEvents()不宜被调用的过于频繁,也不宜被调用的不够频繁,过于频繁的话,一方面会使线程的响应更好,但另一方面会导致原本就耗时的任务变得更加耗时;
5 E, w/ r0 W' f# V) E) d不够频繁的话,显然可能会使GUI线程的响应变差,例如每500ms才被调用一次,那么GUI的事件循环就只能500ms才被处理一次,. f! k1 i& w$ F# Q+ U2 g- ^0 ^' N
当然,这个问题可以通过设定processEvents()的第二个形参略微得到缓解,更好的做法是,保证被调的周期
( Q2 V( a) ^9 A, K X% m0 w4 o副作用:(特别注意!)
7 [9 O* A3 p' Z- W# y9 o: x1、在点击按钮之后,这个20s的耗时任务开始执行,尚未执行完毕时,我们点击了GUI的关闭按钮,那么GUI会立即消失,但是这个耗时任务仍然会在后台执行,直到执行完毕,进程才会退出。解决办法:重写关闭事件,在关闭事件的函数中直接结束进程。5 q/ u9 u! \/ @- o" r( C5 r+ @
2、在点击按钮之后,这个20s的耗时任务开始执行,执行到第5秒时,我们再次点击了这个按钮,那么QT又会执行一个新的20s任务,这个新任务完成后,又会接着把第一个20s任务从上次被打断的第5秒继续执行。如果这个任务是可重入的,后果仅仅是被执行了两遍,如果任务不可重入,那情况就彻底糟糕了。解决办法:点击按钮后把这个按钮disable掉,执行完再enable。
& ]8 a8 F# B3 c3 K) y' L* x8 i! _来源地址:/ p* l& w) k- ^/ J
https://blog.csdn.net/qq_31073871/article/details/80472347-END-, @: j$ n) \6 z. E/ I/ t
往期推荐:点击图片即可跳转阅读& n) W8 j; z% i& P0 i
8 ]2 k$ v; a8 r& [/ w
2 L" _9 n. z4 k' m7 s) z0 j; {
$ [" u+ q7 _* Z6 G3 v' d: }7 P; b 9 D a9 ~- M6 C7 b4 R- n* f. m
pfuhryogd136406127725.jpg
1 H; a: V; f- N3 ?: R2 [: p8 e
1 r- Z$ D) b( p' q9 h& X 嵌入式软件工程师,被深夜的硬件调试击碎了傲慢。
5 }$ L5 p, A- ]/ P6 A4 P& K 0 V( s$ b' t$ E$ N. Y! V
3 Q- l; ~) Q9 H' T
$ D4 Z$ n& U7 ?9 \& |. e! m: l, A
' u6 ]6 i* {# N' L) i* }) z
ptw2vfzkwwa6406127825.jpg
0 I, a8 E7 x9 o/ X. Z% G& u0 f) v, t( X 1 n |& R, @1 y$ l: h; ?/ ?, o/ D
把 DeepSeek-R1 大模型部署到RK3588开发板上,看看运行情况如何?5 L! \/ `6 k. F; ~# |# s
, o: O3 ~; a( ^; H
) A+ A( \/ I' m! p' ]/ K - q' d+ O1 t5 n' j2 e) s0 N* v
nwcysosucrb6406127926.jpg
7 H% E8 D1 e6 U) b
) V/ ~/ n6 [3 `0 J! ` 不久的将来,Rust 会成为主流的嵌入式软件编程语言吗?
2 o* o; c; ]2 g$ k4 x8 ] , T& r, h, A& f/ |
3 C4 a- d- Q, F/ z# W7 z ) y# G! R; O+ ~& e- {5 n
我是老温,一名热爱学习的嵌入式工程师
6 s4 u$ r8 X0 X0 A( D6 z) G关注我,一起变得更加优秀! |