Разница между DispatchSourceTimer, Timer и asyncAfter? - PullRequest
19 голосов
/ 13 марта 2019

Я изо всех сил пытаюсь понять основные различия между DispatchSourceTimer , Таймер и asyncAfter ( в моем случае для планирования задачи, которая должна быть запускается каждые X секунд, хотя понимание различий в таймерах может быть полезно для ) (или есть другой (более эффективный) механизм планирования в Swift помимо перечисленных таймеров?).

A Timer нужен активный цикл выполнения в текущей очереди, в которой он был запущен. A DispatchSourceTimer это не нужно. Timer удерживает процессор от перехода в состояние ожидания. Это относится и к DispatchSourceTimer / asyncAfter?

В какой ситуации Timer предпочтительнее, чем DispatchSourceTimer / asyncAfter? И, конечно, разница между всеми ними?

Я хочу планировать работу каждые 15 секунд в своем приложении в частной очереди. Это означает, что мне нужно использовать DispatchSourceTimer, потому что я нахожусь в очереди, которая не является основным потоком (или добавляю в очередь runloop и использую Timer). Однако я не вижу никакой выгоды даже от использования Timer во-первых. Может быть, есть другая операция, которую я могу использовать, чтобы этот график работал каждые 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()

Каковы минусы и плюсы всех таймеров? Когда я должен использовать один над другим? Какой таймер наиболее эффективен? Я придумал следующее:

Таймер

Плюсы:

  • Может быть признано недействительным
  • Ссылка не требуется
  • Может быть остановлено, когда это запланировано.

Минусы:

  • Не позволяет процессору работать без дела
  • Требуется запустить в очереди с циклом выполнения (иначе ничего не происходит, даже без триггера подтверждения ...)

DispatchSourceTimer

Плюсы:

  • Может быть отменено
  • Не требуется цикл запуска

Минусы:

  • Нуждается в сильной ссылке, иначе он немедленно освобождается

asyncAfter

Плюсы: - Не требуется цикл выполнения

Минусы: - не может быть отменено (я думаю)

Есть ли еще таймеры? Почему так много таймеров? Я ожидал реальной разницы между таймерами, но не смог их найти.

Здесь много вопросов, которые вы можете прочитать. Главный вопрос: какие таймеры доступны и какие таймеры следует использовать в каком случае и почему?

1 Ответ

23 голосов
/ 25 марта 2019

Таймер - это быстрый мост NSTimer, который восходит к NeXTSTEP, задолго до появления Grand Central Dispatch (GCD) и таких вещей, как DispatchSourceTimer, который появился только до 10.6 (в форме dispatch_source_set_timer) и dispatchAfter (в форме dispatch_after).

NSTimer основан на цикле выполнения, который был основным способом параллелизма до GCD.Это кооперативная система параллелизма, предназначенная для запуска в одном потоке на одном ядре (хотя она может быть расширена до многопоточных сред).

Хотя цикл выполнения все еще очень важен в Какао, онбольше не является основным или даже предпочтительным способом управления параллелизмом.Начиная с 10.6, GCD становится все более предпочтительным подходом (хотя добавление API NSTimer на основе блоков в таймфрейме 10.12 было желанной модернизацией).

В масштабе 15 секунд различия в эффективности довольно несущественны.Тем не менее, я не понимаю ваш комментарий «Таймер удерживает процессор от перехода в состояние ожидания».Я не верю, что это правда.Процессор определенно все еще будет переходить в состояние ожидания при ожидании срабатывания NSTimer.

Я бы не устанавливал цикл запуска только для запуска NSTimer.Вам было бы намного лучше запланировать это в главном цикле выполнения, а затем использовать DispatchQueue.async для выполнения фактической работы в какой-то другой очереди.

Как правило, я использую инструмент самого высокого уровня, который удовлетворяет потребности,Это те, которые Apple, вероятно, оптимизирует лучше всего со временем, когда я внесу наименьшее количество изменений.Например, даты пожара NSTimer автоматически корректируются для повышения энергоэффективности.С DispatchSourceTimer вы получаете контроль над параметром leeway, чтобы получить то же преимущество, но вы можете установить его (по умолчанию - ноль, что оказывает наименьшее влияние на энергию).Конечно, верно и обратное.DispatchSourceTimer является самым низким уровнем и дает вам максимальный контроль, поэтому, если это то, что вам нужно, это тот, который нужно использовать.

Для вашего примера я лично, вероятно, использовал бы Таймер и просто отправлял бы в частную очередькак часть блока.Но DispatchSourceTimer был бы полностью уместен.

asyncAfter - это действительно другая вещь, так как это всегда один выстрел.Это замечательно, если вы хотите один выстрел, но он меняет вещи, если вы хотите повторить.Если вы просто вызовете asyncAfter в блоке, чтобы повторить, это будет через 15 секунд после того, как вы в последний раз закончили, вместо того, чтобы быть разнесенными на 15 секунд.Первый будет иметь тенденцию дрейфовать немного позже со временемВопрос в следующем: если по какой-то причине ваша задача заняла 5 секунд, вы бы хотели, чтобы следующий пожар произошел через 15 секунд после его окончания, или вы хотите, чтобы между каждым событием пожара оставались постоянные 15 секунд?Ваш выбор там определит, какой инструмент правильный.

В качестве небольшого примечания, события NSTimer всегда немного позже, чем они запланированы.Мероприятия GCD с задержкой могут быть немного раньше или немного позже.С практической точки зрения, нет такой вещи, как «вовремя» (это период нулевой длины; вы не собираетесь его ударить).Таким образом, вопрос всегда в том, обещали ли вы опоздать, как NSTimer, или вы можете быть рано, как GCD с задержкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...