В чем разница между DispatchQueue.global(qos: .background).async {} и Task(priority: .background) {} ​​в Swift

Я вижу, что Swift поддерживает 2 вида фоновых задач.

Используя DispatchQueue

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

Используя Task

Task(priority: .background) {} 

Итак, я не понимаю, в чем разница и какой из них мне следует использовать?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
131
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Task — это относительно новый API, который является частью Swift Concurrency , тогда как DispatchQueue существуют уже давно. Дополнительную информацию см. в документации.

Если вы хотите использовать Swift Concurrency в своем коде (например, писать функции async вместо использования шаблона обработчиков завершения), вам следует использовать Task и связанные с ним API. Как правило, смешивать Swift Concurrency с очередями отправки не рекомендуется. Это очень разные API с очень разными базовыми концепциями.

В частности, для двух показанных вами фрагментов кода основное различие заключается в том, что DispatchQueue.global() не запускает ваш код в основном потоке, тогда как Task { ... } запускает ваш код в основном потоке, если вы вызываете его из изолированного MainActor контекста. То есть Task.init наследует контекст актера. Чтобы запустить Task из основного потока, используйте Task.detached.

Ответ принят как подходящий

Это два совершенно разных шаблона (несмотря на внешне схожую ссылку на приоритет .backgroundQoS /). Эти два подхода используются в совершенно разных ситуациях. Это сильное упрощение, но:

Итак, вопрос более фундаментальный, чем DispatchQueue.global.async {…} vs Task {…}. Настоящий вопрос — параллелизм GCD и Swift. (И мы почти всегда избегаем смешивания GCD с параллелизмом Swift, за исключением случаев, когда это абсолютно необходимо, но это выходит за рамки этого вопроса. Обычно мы выбираем параллелизм GCD или Swift и последовательно используем этот конкретный технологический стек в рамках данного проекта.)

В современных базах кода мы бы приняли параллелизм Swift (и, таким образом, отдали бы предпочтение Task {…} или, где это возможно, придерживались структурированного параллелизма), но если вы обременены некоторой устаревшей кодовой базой GCD, то вы можете использовать глобальные очереди отправки для медленного/синхронного работа.


Кстати, я бы посоветовал немного разобраться с термином «фоновая задача». В частности, я мог бы посоветовать вам не путать этот термин с параллелизмом Swift TaskPriority .background или глобальной очередью отправки с QoSClass .background).

Традиционно, когда мы абстрактно говорим о «фоновой задаче», мы имеем в виду «вытащить ее из текущего потока». Но «приоритет» задачи и/или очередь отправки «качество обслуживания» — это скорее вопрос относительного приоритета этой работы по отношению к другой также представленной работе.


Наконец, стоит отметить, что Task {…} не работает вне текущего контекста. На самом деле всё наоборот: Задача {…} будет запускать работу от имени текущего актера. Использование Task.detached {…}, вероятно, ближе к идее глобальной очереди отправки, но даже это несовершенная аналогия.

Для получения дополнительной информации см. Язык программирования Swift: Параллелизм: неструктурированный параллелизм или видеоролики WWDC 2021 Встречайте async/await и Swift concurrency: За кулисами.

Другие вопросы по теме