-->

的NSTimer不及时解雇(NSTimer is not fired in time)

2019-09-19 13:57发布

我试图连接到端口上的指定IP地址。 一个问题是,当建立了与不存在的IP的连接地址的写入命令(这是如下):

NSData * imageRequest = [@"640" dataUsingEncoding: NSUTF8StringEncoding];

int image = [self.outputImageStream write:[imageRequest bytes] maxLength:[imageRequest length]];

这需要超过75秒的响应。 我试图通过启动用下面的方法调用一个计时器这个处理:

self.connectionTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(respondToTimer:)userInfo:nil repeats:NO];

它不是1秒间隔I定义中调用。

有没有什么办法,以保证在1秒钟内定时器触发?

Answer 1:

这可能会回答你的问题关于的NSTimer实时行为 :

计时器不是实时的机制; 它触发只有在其计时器已添加运行循环模式之一运行,并能够检查是否计时器的发射时间已经过去了。 因为一个典型的运行循环管理的各种输入源,用于定时器的时间间隔的有效分辨率被限制为50-100毫秒的数量级上。 如果在很长的标注或同时运行循环是在未监视定时器的模式发生了计时器的烧成时间,计时器不火,直到下一次运行循环检查计时器。 因此,实际的时间,让定时器触发潜在可能的时间预定发射时间后,显著的时期。

你不指定要如何调度的NSTimer,但如果你将其排定您可能会发现其性能有所改善NSRunLoopCommonModes代替NSRunLoopDefaultModes

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

如果这没有改善的事情,那么你应该去找下级的替代品。

特别是,你可能会考虑CADisplayLink

一个CADisplayLink对象是一个计时器对象,它允许您的应用程序其绘图同步到显示器的刷新速率。

其可以在一个相当类似的方式的NSTimer使用。

CADisplayLink的优点是,它链接到的刷新率,所以它应该给为1/60秒的时间间隔非常可靠的行为。

使用CADisplayLink的实施例:

CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(respondToTimer)];
[displayLink setFrameInterval:60];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

这将调用respondTimer每60个刷新帧,即每秒一次。 因为你希望你的方法只是一个调用,您可以使用:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC),
                           dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                               [self respondToTimer];
                           });

这将是对你可能更容易。 (当然你可以调用替换为[自respondToTimer]全面实施该方法)。



文章来源: NSTimer is not fired in time