常用的延时调用

常用的几种延时调用简介
  • iOS中的几种常用定时器,是否严格按照设定的时间间隔按时执行,支持的最小时间间隔
NSTimer
  • 可以精确到50-100毫秒. 能满足对间隔要求不严格、对精确度不敏感的需求

    • NSTimer理论上最小精度为 0.1 毫秒。不过由于受 Runloop 的影响,会有 50 ~ 100 毫秒的误差,所以,实际精度可以认为是 0.1 秒。
    • 不可靠,NSTimer不是绝对准确的,而且中间耗时或阻塞错过下一个点,那么下一个点就pass过去了.timer其所在的RunLoop会定时检测是否可以触发NSTimer的事件.但由于iOS有多个RunLoop的运行模式,如果被切到另一个runloop, NSTimer就不会被触发.每个RunLoop的循环间隔也无法保证,当某个任务耗时比较久,RunLoop的下一个消息处理就只能顺延,导致NSTimer的时间已经到达,但Runloop却无法及时触发 NSTimer,导致该时间点的回调被错过。
  • 创建方法:


+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;
  • 除了参数区别之外.这五种初始化方法的不同之处在于:

    • timerWith这两个类方法以及init方法,只是创建了定时器,必须手动加入到当前runloop中去.如果不手动加入主循环池中,将不会循环执行。并且如果不手动调用fire,则定时器不会启动。
    • scheduled这两个类方法是创建一个定时器,并加入到当前运行循环中.不需要手动调用fire,会自动执行。

      • 使用 [timer fire];可以触发定时器.
      • fire并不是启动一个定时器,只是提前触发而已.
      • 在重复执行(repeat = YES)的定时器中调用此方法后立即触发该定时器,但不会中断其之前的执行计划;
      • 在不重复执行(repeat = NO)的定时器中调用此方法,立即触发后,就会使这个定时器失效。

      • 销毁定时器,使用 [timer invalidate]; 这是唯一将定时器从循环池中移除的方法.

NSObject的 performSelector
  • NSObject对NSTimer封装后提供的一个比较简单的延时方法.当调用NSObject的performSelecter:afterDelay:后,实际上其内部会创建一个Timer并添加到当前线程的RunLoop中.所以这种方法的精确度和可靠性同timer.

  • 使用方法


- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
  • cancle方法

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;
GCD
  • 最小精度为纳秒,误差在50毫秒以内.

  • 比较常用的 dispatch_after方法并没有直接的cancel方法


dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0/*延迟执行时间*/ * NSEC_PER_SEC));

dispatch_after(delayTime, dispatch_get_main_queue(), ^{

});
  • 更加精确的定时器 消耗性能

dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); //创建一个GCD的定时器 dispatch_source_t本质上是OC类,

dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW,3.0 *NSEC_PER_SEC); //设置开始时间
  uint64_t delayTime = 1.0 * NSEC_PER_SEC; //设置定时器工作的间隔时间

dispatch_source_set_timer(timer, start, delayTime, 0 * NSEC_PER_SEC);
   /*
    第一个参数:要给哪个定时器设置
    第二个参数:定时器的开始时间DISPATCH_TIME_NOW表示从当前开始
    第三个参数:定时器调用方法的间隔时间
    第四个参数:定时器的精准度,如果传0则表示采用最精准的方式计算,如果传大于0的数值,则表示该定时切换i可以接收该值范围内的误差,通常传0
    该参数的意义:可以适当的提高程序的性能
    注意点:GCD定时器中的时间以纳秒为单位
    */

//设置定时器开启后回调的方法
dispatch_source_set_event_handler(timer, ^{

    });
//执行定时器
dispatch_resume(timer);
  • 取消方法

dispatch_source_cancel(_recordTimer);
# 这些是比较常用的,一般使用场景下的也足够了,如果需要更精确的,系统有给提供误差更小的高精度定时器
### 关于 RT-Thread 中延时函数的使用 在 RT-Thread 实时操作系统中,提供了多种方式来实现任务或线程的延迟操作。最常用的是 `rt_thread_delay` 函数,该函数允许指定的时间单位为滴答数(tick),这取决于系统的时钟频率设置。 #### 使用 `rt_thread_delay` 此函数可以在线程内部调用来暂停当前线程一段时间,在这段时间内其他就绪状态下的高优先级线程有机会获得 CPU 资源运行[^1]: ```c #include "rtthread.h" // 延迟 n 个 tick 时间 void delay_n_ticks(rt_uint32_t ticks) { rt_thread_delay(ticks); } ``` 如果希望基于更直观的时间单位(如毫秒),则可以通过计算转换成相应的滴答数再传递给上述接口。通常情况下,RT-Thread 提供了一个宏定义 `RT_TICK_PER_SECOND` 来表示每秒钟产生的滴答次数,因此可以根据它来进行简单的换算: ```c #define MS_TO_TICKS(ms) ((ms)*(RT_TICK_PER_SECOND/1000)) int main(void) { // 延迟 500 毫秒 rt_thread_delay(MS_TO_TICKS(500)); return 0; } ``` 需要注意的是,当调用这些阻塞式的延时API时,会使得当前上下文进入等待队列直到计时期满才会被唤醒继续执行后续代码逻辑;而在中断服务程序(ISR)里不应该直接调用此类可能导致调度变化的操作以免破坏内核稳定性[^2]。 对于某些应用场景下可能还需要考虑非阻塞性质的延时处理方案,这时就可以利用定时器组件配合回调机制完成特定需求而不影响主线流程控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值