【问题标题】:Timer is being fired twice and not nilled计时器被触发两次并且没有被取消
【发布时间】:2018-01-16 13:12:12
【问题描述】:

我正在遵循this 答案中给出的建议。我的计时器仍然是 sometimes not nil

func recreateTimer(){

        let timerLog = OSLog(subsystem: "LocationLogger", category: "Timer")

        guard shouldUseTimer == true else {
            os_log("we are using CoreMotion, no need to set timer", log: timerLog, type: .error) 
            return
        }
        if dwellingTimer != nil{

            dwellingTimer?.invalidate()
            dwellingTimer = nil
        }

        lastDwelling = lastLocation

        os_log("Moved more than 160 | invalidated previous timer began new timer", log: timerLog, type: .error)

        DispatchQueue.main.async { [weak self] in

            guard self?.dwellingTimer == nil else{
                os_log("Timer was not niled!!!", log: timerLog, type: .error)
                return
            }
            self?.dwellingTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: false, block: { timer in
                os_log("we reached 1 minute of no movement",log: timerLog, type: .fault)
                self?.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
                self?.beginMotionTracking()
                os_log("Timer is deallocated & invalidated | Accuracy: %{public}f | RemainingTime: %{public}f",log: timerLog, type: .fault,(self?.locationManager.desiredAccuracy)!, UIApplication.shared.remainingTime())
            })
        }
        os_log("New Timer is 'likely' set now", log: timerLog, type: .error)
    }

有时我会被点击

os_log("we are using CoreMotion, no need to set timer", log: timerLog, type: .error).

【问题讨论】:

  • 在 dispatchq 块中生成计时器是否可能是问题?
  • 你应该在串行调度队列上同步调度你的dwellingTimer属性的所有更新,以确保操作是线程安全的
  • @Paulw11 我一定会这样做的。我想我需要做的是创建一个串行队列并将计时器添加到主运行循环,或者只是将失效和nilling 放入DispatchQueue.main.async... 但是我不明白这怎么可能从一开始就是一个问题......主线程是一个串行队列,并且if dwellingTimer != nil{... 行也以串行方式调用。所以每个部分都应该没问题...
  • @Paulw11 实际上让我们假设我收到 3 个超快速调用,niled、niled、niled、scheduled、scheduled、scheduled(即我不会得到 niled、scheduled、niled、scheduled、niled 计划)- -> 所以我得到 3 个计时器而不是 1 个?!嗯,如果这就是你的意思,那么即使dispatch.main.async 也无济于事,因为它不是你所说的synchronously,我必须手动完成,即创建线程添加计时器到运行循环......请纠正我曾经在哪里错了
  • 是的,对属性的访问可能不是原子的,并且异步调度将在当前函数返回后的某个时间发生。如果您在原子操作中更新属性(并在必要时安排计时器)(如果需要,通过 dispatch_sync),那么您将防止这种情况发生

标签: ios swift multithreading timer nstimer


【解决方案1】:

感谢螺线管和 Paulw11 cmets,我了解到与计时器相关的所有执行都应该以串行方式完成。

另见invalidate

您必须从计时器所在的线程发送此消息 已安装。如果您从另一个线程发送此消息,则输入 与计时器关联的源不能从其运行循环中删除, 这可能会阻止线程正常退出。

因此,除了invalidatingnilling(您不想为不再传达任何含义的对象提供非nil)之外,请确保您:

  1. 使用相同的线程
  2. 您使用的线程是串行的
  3. 取决于您对计时器进行更改的位置,您可能需要也可能不需要同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    相关资源
    最近更新 更多