Пока вы не отправляете в основную очередь (или какую-либо другую очередь, которая использует основную очередь в качестве своей «цели»), async
никогда не будет использовать основной поток. Есть несколько интересных оптимизаций с sync
, которые влияют на то, какой поток используется (что здесь не имеет значения), но не для async
. Асинхронно отправляемая задача будет выполняться в рабочем потоке, связанном с этим QoS, а не в основном потоке.
Итак, go вперед и вставьте утверждение потока в свой тест, чтобы убедиться, что оно не в основном потоке, и я думаю, вы обнаружите, что это нормально:
XCTAssertFalse(Thread.isMainThread, "Shouldn't be on main thread")
Сказанное выше означает, что вы ссылаетесь на тот факт, что «сама функция использует основной поток». Если это так, вы можете легко заблокироваться, если ваш тест блокирует основной поток, ожидая, пока вызываемые функции завершат обработку sh в основном потоке.
Вы часто можете избежать такого рода взаимоблокировок модульного теста, используя «ожидания».
func testWillNotDeadlock() throws {
let expectation = self.expectation(description: "testWillNotDeadlock")
someAsyncMethod {
expectation.fulfill()
}
waitForExpectations(timeout: 100)
}
В этом случае, хотя someAsyncMethod
мог использовать основной поток, мы не тупик, потому что мы убедились, что тест использует ожидания, а не блокирует текущий поток.
Итак, в итоге, если вы тестируете некоторые асинхронные методы, которые должны использовать основной поток, убедитесь, что тесты не блокируют, а скорее используют ожидания.
Конечно, есть и другие источники потенциальных проблем. Например, вы вызываете async
со 100 итерациями. Вам нужно быть осторожным с этим шаблоном, потому что вы можете легко исчерпать все рабочие потоки с помощью этого «взрыва потока». Попытка ввести concurrentPerform
(который часто используется для решения проблем разрыва потока) не сработает, если код в закрытии вызывает async
.