В каком потоке выполняется async-метод, вызванный внутри Task, созданного в обычной (не изолированной) функции?

«В каком потоке выполняется async-метод, вызванный внутри Task, созданного в обычной (не изолированной) функции?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Он выполняется в произвольном потоке из cooperative thread pool Swift Concurrency.

Ключевые принципы:

  1. Наследование контекста: Task наследует актор-контекст места своего создания. Если он создан вне MainActor (в обычной синхронной функции), у него нет привязки к главному потоку.
  2. Пул потоков: Система Swift Concurrency выбирает для выполнения тела async-функции любой доступный поток из своего пула.

Пример:

// 1. Обычная синхронная функция, не изолированная к MainActor.
func startBackgroundWork() {
    Task { // Эта задача НЕ привязана к MainActor.
        // Код до `await` выполняется в потоке из пула (A).
        print(Thread.current) // Не главный
        await asyncOperation()
        // Код после `await` может выполниться в том же или ДРУГОМ потоке из пула (B).
    }
}

// 2. Async-функция, вызванная внутри задачи.
func asyncOperation() async {
    // Выполняется в потоке из пула Swift Concurrency.
    let result = await downloadData()
}

Как управлять потоком?

  • Используйте @MainActor для гарантии выполнения на главном потоке.
  • Используйте глобальные акторы (@GlobalActor) для собственных изолированных контекстов.
  • Task.detached явно создает задачу, не наследующую контекст родителя.