简体   繁体   English

DispatchTime.asyncafter的一致性

[英]Consistency of DispatchTime.asyncafter

In my iPad app I am trying to get a tableView to scroll at pre-determined intervals. 在我的iPad应用程序中,我试图让tableView以预定间隔滚动。 To do this I have created a piece of code that creates a closure for each scroll. 为此,我创建了一段代码,为每个滚动创建了一个闭合。 However the closure is executed seconds later than when I wanted. 但是,关闭比我想要的要晚几秒钟执行。 Here is a simplified Playground which exemplifies the same problem. 这是一个简化的游乐场,它例证了相同的问题。

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// Intervals at which the delayed closures should run
var lengths: [Double] = [0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 
    12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0]
var times: [UInt64] = []

let dispatchStartTime = DispatchTime.now()

for index in 0 ..< lengths.count
{
    let delayNanoSeconds = Int(lengths[index] * 1_000_000_000)
    let dispatchLength = dispatchStartTime + .nanoseconds(delayNanoSeconds)
    times.append(dispatchLength.rawValue)

    DispatchQueue.main.asyncAfter(deadline: dispatchLength)
    {
        let delay = Double(DispatchTime.now().rawValue - times[index])
        print(delay/1_000_000_000)
    }
}

Upon running this I received the following results: (similar results for other trials, and for the code running in my app) 运行此程序后,我收到以下结果:(其他试验以及应用程序中运行的代码的结果相似)

0.01646185
0.190259978
0.000302805
0.59319351
0.732933723
0.938841374
1.08249717
1.326286228
8.6309e-05
0.00019526
0.000104861
2.19584049
0.196220036
2.000116042
0.000425943
0.000202886

I can tolerate an error of 50-100 ms. 我可以容忍50-100毫秒的错误。 However from the results we can see that the error can be greater than 2 seconds, and it appears to grow with time/amount of closures. 但是,从结果中我们可以看到该错误可能大于2秒,并且它似乎随着关闭时间/关闭量的增加而增加。 In my app there can be on the order of 100 of such intervals. 在我的应用程序中,此类间隔大约为100。 Is it possible to achieve this level of specificity with asyncAfter or would an alternative such as one thread with a busy wait be a better solution? 是否可以使用asyncAfter达到这种程度的特异性,还是采用诸如等待繁忙的一个线程之类的替代方案更好?

I have implemented a single thread version that relies on mach_wait_until . 我已经实现了一个依赖于mach_wait_until的单线程版本。 This is probably overkill for accuracy, but it doesn't seem to have any strong negative effect on energy use. 这可能会导致准确性过高,但似乎对能源使用没有任何严重的负面影响。

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

var timeInfo: mach_timebase_info = mach_timebase_info(numer: 0, denom: 0)
mach_timebase_info(&timeInfo)
// Intervals at which the delayed closures should run
var lengths: [Double] = [0.0, 2.0, 4.0,6.0,8.0,10.0,12.0,14.0,16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 38.0, 40.0, 42.0, 44.0, 46.0, 48.0, 50.0, 52.0, 54.0, 56.0, 58.0, 60.0, 62.0, 64.0, 66.0, 68.0, 70.0]

let startTime = mach_absolute_time()

DispatchQueue.global().async()
{
    for index in 0 ..< lengths.count
    {
        let delayTicks = UInt64(lengths[index] * 1_000_000_000) * UInt64(timeInfo.denom) / UInt64(timeInfo.numer)
        mach_wait_until(startTime + delayTicks)

        DispatchQueue.main.async()
        {
            // UI changes
        }
    }
}

mach_until_wait() does not seem to work in playgrounds but the code in my app works as intended and doesn't have any noticeable delay. mach_until_wait()似乎不能在操场上工作,但是我的应用程序中的代码可以按预期工作,并且没有明显的延迟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM