多线程 - Swift 中的 DispatchQueue asyncAfter 延迟

Posted

技术标签:

【中文标题】多线程 - Swift 中的 DispatchQueue asyncAfter 延迟【英文标题】:Multithreading - DispatchQueue asyncAfter delay in Swift 【发布时间】:2019-08-06 11:53:06 【问题描述】:

我正在使用以下代码每秒定期调用一个函数。问题是延迟实际上是 1.1 秒,并且最终会越来越漂移,这可以在 NSLogs 中看到(它在代码的其他部分以及除了 NSLog 之外的其他部分中也可见)。我做错了吗,还是我应该使用计时器?

private func updateTimeCode() 
    NSLog("Updating time")
    //Some more code that doesn't take time
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0) 
        [weak self] in
            self ? .updateTimeCode()
    

 019-08-06 17:15:19.713234+0530 MyApp-Swift[8299:2685215] Updating time

 2019-08-06 17:15:20.812652+0530 MyApp-Swift[8299:2685215] Updating time

 2019-08-06 17:15:21.913188+0530 MyApp-Swift[8299:2685215] Updating time

 2019-08-06 17:15:23.028814+0530 MyApp-Swift[8299:2685215] Updating time

【问题讨论】:

我没有使用后台队列。它在主队列上。有错吗? 也许,如果您在主队列上执行任何其他任务。调用该函数会出现一些问题,因为只有一个可用的主队列。按照上面的建议使用 Timer 类。 如何在 Swift 中编写一个可以暂停和恢复的后台计时器? 不相关但[weak self] 毫无意义。 GCD 关闭不会导致保留周期。使用DispatchSourceTimer。它更可靠。 @vadian 我同意提交给 GCD 的块不会导致永久保留周期,但它们仍然会阻止 self 在块执行之前解除分配,这可能会也可能不会根据情况而定.在这种特定情况下,允许self 变强创建一个循环,因为每次块触发它都会重新安排自己,所以weak 在这里完成它的工作(但同意 DispatchSourceTimer 可能是正确的工具)。 【参考方案1】:

这是因为您所说的更多代码不相关的部分需要时间。它们在每次调用asyncAfter 之间需要时间和时间,所以基本上.now() 变成了超过 1 秒前的东西。

无论如何,这不是实现它的传统方式。为此,您需要使用计时器。这是有关如何使用它的有用教程。 Timer in Swift

【讨论】:

以上是关于多线程 - Swift 中的 DispatchQueue asyncAfter 延迟的主要内容,如果未能解决你的问题,请参考以下文章

GCD多线程在swift中的变化

通用字典类的 Swift 编译器错误:无法使用类型为“(forKey K)”的参数列表调用“removeValue”

iOS中的同步与异步队列

Swift系列三十一 - 多线程

Swift - 多线程GCD详解

在多线程环境中写入时的 Swift 数组复制