草庐IT

swift - DispatchSourceTimer、Timer 和 asyncAfter 之间的区别?

coder 2023-07-15 原文

我很难理解 DispatchSourceTimer 之间的主要区别, TimerasyncAfter (在我的例子中,调度一个需要每 X 秒运行一次的任务,尽管了解定时器的差异可能对有用)(或者除了列出的计时器?)。

Timer 需要在其启动所在的当前队列上有一个事件的运行循环。 DispatchSourceTimer 不需要它。 Timer 防止 CPU 进入空闲状态。这是否也适用于 DispatchSourceTimer/asyncAfter

在什么情况下 Timer 优于 DispatchSourceTimer/asyncAfter?当然还有它们之间的区别?

我想在我的应用程序中的私有(private)队列中每 15 秒安排一次工作。这意味着我必须使用 DispatchSourceTimer,因为我在一个不是主线程的队列中(或者向队列添加一个运行循环并使用 Timer)。但是,我什至一开始就没有看到使用 Timer 有任何好处。也许还有另一种操作,我可以在私有(private)队列上每 X 秒使用一次调度工作,这比 DispatchSourceTimer 更有效,但我没有找到更好的解决方案。

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

这是创建计时器的代码。

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()

所有计时器的优缺点是什么?我什么时候应该在另一个之上使用一个?哪种定时器方式最有效?我想出了以下内容:

计时器

优点:

  • 可以失效
  • 无需引用
  • 可以按计划停止。

缺点:

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

DispatchSourceTimer

优点:

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

缺点:

  • 需要一个强引用,否则它会立即被释放

异步之后

优点: - 不需要运行循环

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

还有更多的计时器吗?为什么有这么多定时器?我希望所有不同的计时器都有一些真正的区别,但我找不到它们。

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

最佳答案

Timer 是 NSTimer 的 Swift 桥接器,它可以追溯到 NeXTSTEP,远早于 Grand Central Dispatch (GCD) 和诸如 DispatchSourceTimer 之类的东西,直到 10.6(以 dispatch_source_set_timer 的形式)和 dispatchAfter (以 dispatch_after 的形式)。

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

虽然运行循环在 Cocoa 中仍然非常重要,但它不再是管理并发的主要方式,甚至不再是首选方式。自 10.6 以来,GCD 一直是越来越受欢迎的方法(尽管在 10.12 时间框架中添加基于 block 的 NSTimer API 是一个受欢迎的现代化)。

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

我不会为了运行 NSTimer 而设置运行循环。您最好将其安排在主运行循环上,然后使用 DispatchQueue.async 在其他队列上执行实际工作。

一般来说,我会使用满足需求的最高级别的工具。随着时间的推移,这些是 Apple 可能会优化得最好的,而我所做的更改最少。例如,NSTimer 的触发日期会自动调整以提高能源效率。使用 DispatchSourceTimer,您可以控制 leeway 设置以获得相同的好处,但设置它取决于您(默认值为零,这对能量的影响最差)。当然,反之亦然。 DispatchSourceTimer 是最低级别并为您提供最多的控制权,因此如果您需要它,就可以使用它。

对于您的示例,我个人可能会使用 Timer 并将其作为 block 的一部分分派(dispatch)到专用队列。但是 DispatchSourceTimer 是完全合适的。

asyncAfter 确实是另一回事,因为它始终是一次性的。如果你想要一次性,那很好,但如果你想重复,它会改变事情。如果您只是在要重复的 block 中调用 asyncAfter,它将在您上次完成后 15 秒,而不是间隔 15 秒。随着时间的推移,前者往往会漂移得晚一些。设计问题是这样的:如果由于某种原因您的任务需要 5 秒才能完成,您是否希望下一次火灾事件在该事件结束后 15 秒发生,或者您希望每次火灾事件之间保持恒定的 15 秒?您的选择将决定哪个工具是正确的。

作为一个小提示,NSTimer 事件总是比它们计划的晚一点。有余地设置的GCD事件可以早一点也可以晚一点。实际上,没有“准时”这样的事情(那是一个零长度的时间段;你不会按时完成)。所以问题始终是你是否 promise 像 NSTimer 一样迟到,或者你可能像 GCD 一样有余地早。

关于swift - DispatchSourceTimer、Timer 和 asyncAfter 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55131532/

有关swift - DispatchSourceTimer、Timer 和 asyncAfter 之间的区别?的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  3. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  4. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  5. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  6. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  7. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  8. ruby - 这两段代码有什么区别? - 2

    打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性

  9. ruby - Ruby 中 .next 和 .succ 的区别 - 2

    Ruby中的Fixnum方法.next和.succ有什么区别?看起来它的工作原理是一样的:1.next=>21.succ=>2如果有什么不同,为什么有两种方法做同样的事情? 最佳答案 它们是等价的。Fixnum#succ只是Fixnum#next的同义词。他们甚至在thereferencemanual中共享同一block. 关于ruby-Ruby中.next和.succ的区别,我们在StackOverflow上找到一个类似的问题: https://stacko

  10. ruby - 在参数为 `yield self` 的方法中使用 `&block` 和在没有参数 `yield self` 的方法中使用 `&block` 有什么区别吗? - 2

    我明白了defa(&block)block.call(self)end和defa()yieldselfend导致相同的结果,如果我假设有这样一个blocka{}。我的问题是-因为我偶然发现了一些这样的代码,它是否有任何区别或者是否有任何优势(如果我不使用变量/引用block):defa(&block)yieldselfend这是一个我不理解&block用法的具体案例:defrule(code,name,&block)@rules=[]if@rules.nil?@rules 最佳答案 我能想到的唯一优点就是自省(introspecti

随机推荐