DispatchSourceTimer,Timer和asyncAfter之间的区别? [英] Difference between DispatchSourceTimer, Timer and asyncAfter?

查看:139
本文介绍了DispatchSourceTimer,Timer和asyncAfter之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力了解 DispatchSourceTimer

I am struggling to understand the key differences between DispatchSourceTimer, Timer and asyncAfter (in my case for scheduling a task that needs to be ran every X seconds, although understanding the differences in timers can be useful to) (Or is there another (more efficient) scheduling mechanism in Swift besides the listed timers?).

Timer需要在其开始的当前队列上有一个活动的运行循环. DispatchSourceTimer不需要. Timer可防止CPU进入空闲状态.这是否也适用于DispatchSourceTimer/asyncAfter?

A Timer needs an active run loop on the current queue it was started on. A DispatchSourceTimer does not need that. A Timer keeps the CPU from going into the idle state. Does this apply to DispatchSourceTimer/asyncAfter as well?

在什么情况下,TimerDispatchSourceTimer/asyncAfter更受青睐?当然,它们之间的区别是什么?

In what situation a Timer is preferred over a DispatchSourceTimer/asyncAfter? And of course the difference between all of them?

我想在私人队列中的应用程序中每15秒安排一次工作.这意味着我必须使用DispatchSourceTimer,因为我所在的队列不是主线程(或者将runloop添加到队列中并使用Timer).但是,即使一开始使用Timer,我也看不到任何好处.也许还有另一种操作,我可以在私人队列上每X秒使用该调度工作,它比DispatchSourceTimer效率更高,但是我没有遇到更好的解决方案.

I want to schedule work every 15 seconds in my application on a private queue. This means I have to use DispatchSourceTimer because I am on a queue that is not the main thread (or add a runloop to the queue and use Timer). However, I do not see any benefit of even using a Timer in the first place. Maybe there is another operation that I can use that schedule work every X seconds on a private queue that is more efficient than a DispatchSourceTimer, but I did not came across a better solution.

DispatchSourceTimer是否比Timer更有效?还是应该使用asyncAfter进行自调用方法?

Is a DispatchSourceTimer more efficient than a Timer? Or should I go on a self-calling method with asyncAfter?

这是创建计时器的代码.

This is the code to create the timers.

asyncAfter

DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(2)) {
    // Code
}

计时器

Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
    // Code
}

DispatchSourceTimer

let timer = DispatchSource.makeTimerSource()

timer.schedule(deadline: .now() + .seconds(1))

timer.setEventHandler {
    // Code
}

timer.activate()

所有计时器的利弊是什么?我什么时候应该在另一个之上使用?哪种计时器方式最有效?我提出了以下建议:

Whats are the cons and pros of all the timers? When should I use one above the other? What timer way is the most efficient? I came up with the following:

优点:

  • 可以无效
  • 不需要参考
  • 可以在预定的时间停止.

缺点:

  • 防止CPU闲置
  • 需要在具有运行循环的队列上运行(否则什么也没有发生,甚至没有断言触发器...)

优点:

  • 可以取消
  • 不需要运行循环

缺点:

  • 需要一个强有力的参考,否则它会立即被释放

优点: -无需运行循环

Pros: - No run loop needed

缺点: -无法取消(我认为)

Cons: - Can not be cancelled (I think)

还有更多的计时器吗?为什么有那么多计时器?我期望所有不同的计时器之间都存在真正的差异,但是我找不到它们.

Are there even more timers? Why are there so many timers? I expected some real difference across all the different timers, but I couldn't find them.

这里有很多问题,您可以阅读.主要问题是:哪些计时器可用,在什么情况下应使用什么计时器?为什么?

Alot of questions here as you can read. The main question is: what timers are available and what timers should I use in what case and why?

推荐答案

Timer是NSTimer的快速桥梁,它可以追溯到NeXTSTEP,早在Grand Central Dispatch(GCD)和DispatchSourceTimer之类的东西之前就没有了.直到10.6(以dispatch_source_set_timer的形式)和dispatchAfter(以dispatch_after的形式).

Timer is a Swift bridge of NSTimer, which goes back to NeXTSTEP, long, long before Grand Central Dispatch (GCD) and things like DispatchSourceTimer, which didn't come along until 10.6 (in the form of dispatch_source_set_timer) and dispatchAfter (in the form of dispatch_after).

NSTimer基于运行循环,这是在GCD之前完成并发的主要方式.这是一个协作式并发系统,主要设计为在单个内核上的单个线程上运行(尽管它可以扩展到多线程环境).

NSTimer is based on the run loop, which was the primary way that concurrency was done until GCD. It's a cooperative concurrency system, designed primary to run on a single thread on a single core (though it can be expanded to multi-threaded environments).

尽管运行循环在Cocoa中仍然非常重要,但它不再是管理并发的主要方法,甚至不再是首选方法.从10.6开始,GCD成为越来越受欢迎的方法(尽管在10.12时限中添加基于块的NSTimer API是令人欢迎的现代化方法.)

While the run loop is still very important in Cocoa, it is no longer the primary, or even preferred, way to manage concurrency. Since 10.6, GCD has been the increasingly preferred approach (though adding a block-based NSTimer API in the 10.12 timeframe was a welcome modernization).

在15秒的范围内,效率差异是无关紧要的.就是说,我不理解您的评论计时器阻止CPU进入空闲状态".我不相信那是真的.等待NSTimer触发时,CPU肯定仍会进入空闲状态.

On the scale of 15 seconds, the efficiency differences are pretty irrelevant. That said, I don't understand your comment "A Timer keeps the CPU from going into the idle state." I don't believe that's true. The CPU will definitely still go into the idle state when waiting on an NSTimer to fire.

我不会仅仅为了运行NSTimer而设置运行循环.您最好在主运行循环上调度它,然后使用DispatchQueue.async在其他队列上进行实际工作.

I would not set up a run loop just to run an NSTimer. You would be much better off scheduling it on the main runloop and then using DispatchQueue.async to do the actual work on some other queue.

作为一个宽泛的规则,我使用满足需求的最高级工具.这些都是苹果可能会在我进行最少更改的情况下不断优化的最佳方法.例如,NSTimer的启动日期会自动调整以提高能源效率.使用DispatchSourceTimer,您可以控制leeway设置来获得相同的好处,但要取决于您进行设置(默认值为零,这对能量的影响最严重).当然,反之亦然. DispatchSourceTimer是最低级别的控件,可为您提供最大程度的控制,因此,如果您需要它,那就可以使用它.

As a broad rule, I use the highest-level tool that meets the need. Those are the ones that Apple is likely to optimize the best over time with me making the fewest changes. For example, NSTimer fire dates are automatically adjusted to improve energy efficiency. With DispatchSourceTimer, you get control over the leeway setting to get the same benefit, but it's up to you to set it (the default is zero, which has the worst energy impact). Of course, the reverse is also true. DispatchSourceTimer is the lowest level and gives you the most control, so if that's what you need, that's the one to use.

以您的示例为例,我个人可能会使用Timer并将其作为块的一部分分派到专用队列.但是DispatchSourceTimer完全合适.

For your example, I'd personally probably use a Timer and just dispatch to the private queue as part of the block. But a DispatchSourceTimer would be completely appropriate.

asyncAfter确实是另一回事,因为它始终是一次性的.如果您想一次拍摄,那就太好了,但是如果您想重复拍摄,它会改变一切.如果您只是在块中调用asyncAfter进行重复,则将在您上一次完成操作之后15秒钟,而不是间隔15秒钟.前者会随着时间的流逝而逐渐漂移.设计问题是这样的:如果由于某种原因您的任务花了5秒钟完成,您是否希望下一次火灾事件在结束后15秒钟内发生,还是您希望每个火灾事件之间保持15秒钟不变?您在那里选择将确定哪种工具正确.

asyncAfter is really a different thing, since it's always a one-shot. That's great if you want a one-shot, but it changes things if you want to repeat. If you just call asyncAfter in the block to repeat, it's going to be 15 seconds after the last time you finished, rather than being spaced 15 seconds apart. The former will tend to drift a bit late over time. The design question is this: if for some reason your task took 5 seconds to complete, would you want the next fire event to happen 15 seconds from the end of that, or would you want a constant 15 seconds between each fire event? Your choice there will determine which tool is correct.

作为一个小提示,NSTimer事件总是比计划的时间晚一点.具有回旋余地的GCD事件可以早一点或迟一点.实际上,没有准时"之类的东西(这是一个零长度的时间段;您不会碰到它).因此,问题始终是您是否被保证像NSTimer那样迟到,或者您可能像GCD那样有回旋余地.

As a slight note there, NSTimer events are always a little later than they are scheduled. GCD events with a leeway setting can be a little early or a little late. As a practical matter, there's no such thing as being "on time" (that's a period of zero length; you're not going to hit it). So the question is always whether you are promised to be late like NSTimer, or you might be early like GCD with leeway.

这篇关于DispatchSourceTimer,Timer和asyncAfter之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆