Производительность фоновой очереди в swift? - PullRequest
0 голосов
/ 04 ноября 2018

В продолжение моего вопроса здесь .

У меня есть метод lotsOfWork (), выполнение которого может занять некоторое время. Пока он работает, пользователь должен дождаться его завершения. Я хотел бы оставить отзыв пользователю, чтобы он (и) увидел, что происходит.

Теперь у меня есть следующий код для запуска моего метода lotsOfWork (), позволяющий ему обновлять метку, показывающую его прогресс:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        DispatchQueue.global(qos: .background).async {
            self.lotsOfWork()
        }
    }

    func lotsOfWork() {
        for i in 1...10 {
            DispatchQueue.main.async {
                self.label.text = "Working on item \(i)..."
            }
            sleep(1) // Simulating lots of work
        }
    }
}

Но это также означает, что метод lotsOfWork () будет выполняться в фоновой очереди, а не в основной.

Во время работы lotsOfWork () в основной очереди ничего не происходит, кроме как обновить метку. Пользователь ничего не может сделать, кроме как ждать.

Вопрос 1: Это существенная проблема с производительностью? Потребуется ли для завершения работы больше времени?

Вопрос 2: Если это проблема, есть ли способ, чтобы метод lotsOfWork () выполнялся в main, , при этом сохраняя возможность обновления label.text ?

Я пытался использовать DispatchQueue.main.async и даже 2 вложенных DispatchQueue.main.async, но это не обновляет label.text.

Я также пытался использовать setNeedsDisplay () и setNeedsLayout (), но это ничего не меняет.

Не будет проблем с выполнением LotOfWork () в main, потому что пользователь должен дождаться завершения этой работы, прежде чем продолжить. Но я не могу обновить label.text в режиме реального времени, если в функции main запускается lotOfWork ().

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Запрошенное вами QoS (качество обслуживания) неверно. Вы запросили background:

Используется для работы, которая не инициирована пользователем или не видна. В общем, пользователь не знает, что эта работа даже происходит. Например, предварительная загрузка содержимого, индексация поиска, резервное копирование или синхронизация данных с внешними системами.

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

Если пользователь запросил операцию и должен дождаться ее завершения, тогда правильное QoS будет .userInitiated:

Используется для выполнения работы, которая была явно запрошена пользователем, и результаты которой должны быть немедленно представлены, чтобы обеспечить дальнейшее взаимодействие с пользователем. Например, загрузка электронного письма после того, как пользователь выбрал его в списке сообщений.

Этот уровень QoS может быть (и часто является) таким же быстродействующим, как и основная очередь, хотя в целом следует избегать повторных предположений системы о том, что она будет делать, и просто убедитесь, что вы помечаете операции с QoS, который соответствует цели , Лучшее введение во все это - Параллельное программирование с GCD в Swift 3 .

Я обычно нахожу, что когда люди выбирают .background (самое низкое QoS), они обычно означают .utility, а когда они выбирают .userInteractive (самый высокий уровень), они обычно означают .userInitiated. У самого высокого и самого низкого уровней есть особые случаи использования, которые встречаются не очень часто. Если вам нужен результат менее чем за день, вы не имеете в виду .background, а если для его завершения требуется более 16 мс, вы не имеете в виду .userInteractive.

0 голосов
/ 04 ноября 2018
  1. Согласно найденной Apple документации здесь :

Поскольку работа с более высоким приоритетом выполняется быстрее и с большим количеством ресурсов, чем работа с более низким приоритетом, она обычно требует больше энергии, чем работа с более низким приоритетом. Точное указание соответствующих классов QoS для работы, которую выполняет ваше приложение, гарантирует, что ваше приложение будет отзывчивым и энергоэффективным.

Ответ Да . Очередь с более низким приоритетом может получать меньше ресурсов, поэтому может иметь более медленное выполнение.

  1. Ответ нет . Вы не можете выполнять относительно тяжелую работу на main, не блокируя обновления пользовательского интерфейса.

Если вы заинтересованы в изучении Параллелизма в Swift, я предлагаю вам прочитать этот пост , созданный Умберто Раймонди. Это лучшее руководство по параллелизму Swift, которое я когда-либо видел.

...