Как отменить отложенный поток?

Я выполняю набор задач, и чтобы распределить их по времени, я использовал Thread.sleep(forTimeInterval: ... ) Он добавляет паузы между выполнениями.

Затем на главном экране у меня есть контроллеры, которые могут вмешиваться в выполнение потока, поэтому при применении контроллера я хочу отменить спящий режим. И начать с места по выбору пользователя. Итак, я пробовал Thread.exit() - и он завершает программу с ошибкой.

Как выйти (или обновить) текущий поток и начать с того места, которое я хочу? Какие есть способы управлять приостановкой потока кнопкой (т.е. контроллером)?

Что на самом деле происходит, так это то, что если я отменю, он продолжит работать с того же места...

let queue = DispatchQueue(label: "Actions Queue")
let delay: Double = 5
var actions = ["action 1", "action 2", "action 3", "action 4", "action 5"]


// every time task finishes, it calls for the following task (with delay)
queue.sync {
// sets an interval, that continues an action
    Thread.sleep(forTimeInterval: TimeInterval(delay))
    // continue an action
}

// heres how I've tried in main view, but it doesn't work
queue.sync {
    Thread.current.cancel()
}

РЕДАКТИРОВАНИЕ:

Например, что здесь делает cancel()? и почему exit() нельзя применить к Thread.current, а только к Thread.

Вы можете использовать эту семантику, чтобы отменить выполнение потока или определить, выполняется ли поток еще или завершил свою задачу. Хорошо, если я cancel(). Что тогда начнет снова?

queue.sync {
    Thread.sleep(forTimeInterval: TimeInterval(10.0))
    // do something
}

Button("...") {
    queue.sync {
        Thread.current.cancel()
    }
}

https://developer.apple.com/documentation/foundation/thread


person MikeMaus    schedule 13.02.2021    source источник
comment
Сообщите мне в комментариях, если мне нужно улучшить вопрос; так что я знаю, как я могу это исправить для более качественного обсуждения   -  person MikeMaus    schedule 13.02.2021
comment
Я думаю, вы смешиваете GCD с потоками. Несмотря на то, что они преследуют схожие цели, они находятся на совершенно разных уровнях, поэтому никогда не стоит их смешивать. Я предлагаю вам использовать либо GCD с рабочие элементы или OperationQueue с набором Operations, если вам нужны более сложные взаимодействие между вашими задачами.   -  person ScorpiCon    schedule 13.02.2021
comment
@ScorpiCon, чего я пытаюсь добиться, - иметь презентацию, которая работает с заранее определенным временем между слайдами, но если пользователь хочет вернуться назад (или вперед); он должен сразу переходить к предыдущему слайду и продолжаться таким же образом с заранее определенными паузами. У вас есть какие-то мысли по этому поводу?   -  person MikeMaus    schedule 13.02.2021


Ответы (1)


Как правило, я бы не советовал спать на нитке. Во-первых, у нас нет упреждающей отмены. Во-вторых, это неэффективное использование ресурсов, излишнее затягивание этой нити.

Если вы хотите что-то сделать через определенный промежуток времени, у вас есть несколько вариантов:

  1. Вы можете создать DispatchWorkItem и отправить его с помощью asyncAfter, а затем cancel, если вы не хотите, чтобы это произошло.

  2. Еще проще: запланируйте Timer, а затем invalidate, если вы хотите его остановить.

Если у вас есть какие-то отменяемые задачи, которые вы хотите выполнять каждые x секунд, одиночное повторяющееся Timer, вероятно, будет проще всего, так как вы можете invalidate и оно останавливает всю повторяющуюся серию за один шаг. (Это также позволяет избежать проблем с объединением таймеров.)


Вы сказали:

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

Я бы предложил повторяющееся Timer для перехода к следующему слайду. Если пользователь вручную переключится на другой слайд, invalidate старый таймер создаст новый повторяющийся Timer.

person Rob    schedule 13.02.2021
comment
Спасибо за ответ и ссылки на исследовательскую литературу! Мне стало понятнее! В настоящее время пытаюсь правильно реализовать эту функциональность с помощью Timer. Время отклика программы в 1000 раз быстрее, чем при использовании Threading. - person MikeMaus; 14.02.2021
comment
Прохладный. FWIW, шаблон GCD не должен быть медленнее, но для чего-то повторяющегося, что вы хотите отменить, Timer - это гораздо более простой способ сделать это. Вероятно, в вашей реализации GCD происходило что-то еще, но я думаю, что теперь это не имеет значения, когда у вас есть лучшее решение для приготовления... - person Rob; 14.02.2021