【问题标题】:How to use a timer to stop a long-running function? Swift 4如何使用计时器停止长时间运行的功能?斯威夫特 4
【发布时间】:2019-02-11 03:17:35
【问题描述】:

我有一个可以运行很长时间的函数,如果可能的话,我想给它一个 10 秒的上限。我还想实现一个Cancel 按钮供用户按下。

我尝试在计算时简单地检查 var abort 的状态,但它只是继续工作。我对 Grand Central Dispatchtimers 不是很熟练,不知道从这里去哪里。

...



var abort = false

@objc func abortCalculations() {
    abort = true
}


func calculate() {
    abort = false

    let _ = Timer(timeInterval: 10, target: self, selector: #selector(abortCalculations), userInfo: nil, repeats: false)



    dispatchGroup.enter()
    DispatchQueue.global(qos: .userInteractive).async {
        while !abort {
            x += 1 // for example, just something that repeats
                    // when this actually finishes, it leaves the dispatch group
        }
    }
}



...

我希望函数 calculate() 在计时器停止时完成(或者将来当用户按下按钮时)。相反,它会继续运行,并且永远不会调用函数 abortCalculations()

【问题讨论】:

标签: ios swift xcode timer nstimer


【解决方案1】:

您可以使用类似的DispatchQueue 来设置您的中止标志,而不是使用Timer

var abortFlagItem = DispatchWorkItem(block: {
    self.abort = true
})
DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: abortFlagItem)

如果您想随时取消,可以致电abortFlagItem.cancel()

【讨论】:

  • 实际上还有一个问题:我在一个可重复的函数中有这个,并且计时器正在结转,这意味着如果第一个函数恰好在 5 秒内完成,并且用户按下按钮重复一遍,现在距离第一个计时器仅剩 5 秒。你知道取消第一种计时方法的方法吗?我的不聪明的想法是创建一个布尔数组而不是单个中止布尔,并且每次按下按钮都会在数组中启动一个新条目。然后每个计算检查是否 !abort[x]。当然,效率不高。
  • 由于abort(和self)被两个不同的线程使用,它会导致竞争条件吗?
  • @Cristik 是的,它会在访问 var abort 时。编译器甚至可能将给定的代码while !abort {...} 优化为while true {...}。因此,数据竞赛是一个问题。我们可能倾向于使用读取和修改 var abort 的函数 - 但是,如果没有同步,它仍然是数据竞争 - 编译器 可能 只是无法优化读取访问(除非编译器能够内联函数),这只会使该方法“更频繁地”工作。
猜你喜欢
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
相关资源
最近更新 更多