Ответ
DispatchWorkItem инкапсулирует задачу для выполнения в GCD, предоставляя расширенный контроль.
Ключевые преимущества:
-
Отмена задачи: Возможность отменить выполнение до его начала с помощью
cancel().let workItem = DispatchWorkItem { print("Выполняется") } DispatchQueue.global().asyncAfter(deadline: .now() + 1.0, execute: workItem) workItem.cancel() // Задача не будет выполнена -
Уведомление о завершении: Метод
notify(queue:execute:)позволяет выполнить completion handler.let backgroundItem = DispatchWorkItem { /* Тяжелая задача */ } backgroundItem.notify(queue: .main) { print("Задача завершена, обновляем UI") } DispatchQueue.global().async(execute: backgroundItem) -
Повторное использование: Один
DispatchWorkItemможно выполнить несколько раз на разных очередях. -
Гибкое планирование: Легко комбинируется с
asyncAfterдля отложенного выполнения. -
Приоритет на уровне задачи: Можно задать QoS (Quality of Service) для конкретной задачи, а не всей очереди, с помощью
DispatchWorkItem(qos:flags:block:). -
Синхронное ожидание: Метод
wait()блокирует текущий поток до завершения работы (используйте с осторожностью). -
Проверка состояния: Свойства
isCancelledиisExecutingпозволяют отслеживать статус.
Практический пример:
// Создаем workItem с высоким приоритетом
let dataProcessingItem = DispatchWorkItem(qos: .userInitiated) {
processLargeDataset()
}
// Настраиваем completion
dataProcessingItem.notify(queue: .main) {
self.updateProgressView()
}
// Планируем выполнение с задержкой
DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: dataProcessingItem)
// Возможность отменить, если пользователь ушел с экрана
// dataProcessingItem.cancel() Ответ 18+ 🔞
А, ну вот, смотри, опять эти ваши GCD-шные пляски. Ну ладно, разберёмся, что за зверь такой — DispatchWorkItem. По сути, это просто контейнер, ёпта, для твоей задачи, которую ты хочешь в очередь сунуть. Но не простой контейнер, а с прибамбасами, блядь! Как будто ты не просто кинул анонимную функцию в async, а запаковал её в красивую коробочку с бантиком и кнопкой «отмена».
Чем он, сука, хорош?
-
Отмена — это пиздец как важно. Пока задача не стартанула, можно её послать нахуй методом
cancel(). Представь: запланировал обновление через секунду, а пользователь уже с экрана свалил. Зачем выполнять-то?let workItem = DispatchWorkItem { print("Выполняется") } DispatchQueue.global().asyncAfter(deadline: .now() + 1.0, execute: workItem) workItem.cancel() // И всё, приехали. Эта хуйня уже не напечатается. -
Уведомления о завершении — просто песня. Сделал что-то тяжёлое в фоне, а потом надо на главной очереди UI обновить. Вместо того чтобы внутри блока ещё один блок городить, можно прицепить
notify. Красиво, блядь, элегантно.let backgroundItem = DispatchWorkItem { /* Тяжелая задача, типа парсинг JSON размером с «Войну и мир» */ } backgroundItem.notify(queue: .main) { print("Задача завершена, обновляем UI") // Тут спокойно лезешь к интерфейсу } DispatchQueue.global().async(execute: backgroundItem) -
Повторное использование. Создал один
WorkItem— и можешь его, как похабную пластинку, на разных очередях гонять. Хоть наglobal(), хоть на своей кастомной. -
Планирование. Отлично дружит с
asyncAfter. Запаковал задачу, сказал «выполнись через 2 секунды» и забыл. А она там сама разберётся. -
Приоритет на уровне задачи — вот это мощь! Раньше QoS задавался для всей очереди. А тут можно для конкретной, отдельно взятой задачи указать: «Слушай, дружок, ты у меня
userInitiated, сделай побыстрее, а то пользователь пальцем стучит».let importantItem = DispatchWorkItem(qos: .userInitiated) { // Срочное дело! } -
Синхронное ожидание (
wait). Опа-на! Это когда ты говоришь: «Я тут подожду, пока ты, сука, не выполнишься». Блокирует текущий поток, поэтому юзать надо с умом, а то весь интерфейс встанет колом. Волнение ебать! -
Проверка состояния. Задаёшься вопросом: «А отменили меня уже или нет?» или «Я уже работаю?» — глянь в
isCancelledилиisExecuting. Прозрачность, блядь, полная.
Ну и пример, чтобы вообще всё встало на свои места:
// Создаем workItem с высоким приоритетом, типа «срочно, народ ждёт!»
let dataProcessingItem = DispatchWorkItem(qos: .userInitiated) {
processLargeDataset() // Функция, от которой процессор плачет
}
// Говорим: «Как только закончишь — доложи на главную очередь!»
dataProcessingItem.notify(queue: .main) {
self.updateProgressView() // И обнови там прогресс-бар
}
// А теперь планируем: «Начни через полсекунды, не раньше.»
DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: dataProcessingItem)
// И где-то в другом месте, если надо, можем нажать большую красную кнопку:
// dataProcessingItem.cancel() // Всё, отмена, расходимся.
Вот и весь сказ. Не просто async { }, а контролируемая, отслеживаемая, приоритезируемая единица работы. Иногда — очень удобная хуйня, ей-богу.