Как приостановить программу c
Перейти к содержимому

Как приостановить программу c

Thread. Sleep Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Приостанавливает текущий поток на заданное время.

Перегрузки

Приостанавливает текущий поток на заданное количество миллисекунд.

Приостанавливает текущий поток на заданное время.

Sleep(Int32)

Приостанавливает текущий поток на заданное количество миллисекунд.

Параметры

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

Исключения

Значение времени ожидания является отрицательной величиной и не равно Infinite.

Примеры

В следующем примере метод используется Sleep для блокировки основного потока приложения.

Комментарии

Поток не будет запланирован на выполнение операционной системой в течение указанного времени. Этот метод изменяет состояние включаемого WaitSleepJoinпотока.

Параметр можно указать Timeout.Infinite для приостановки millisecondsTimeout потока на неопределенный срок. Однако рекомендуется использовать другие System.Threading классы, такие как Mutex, Monitorили EventWaitHandleSemaphore вместо этого для синхронизации потоков или управления ресурсами.

Системные часы тикают по определенной частоте, называемой разрешением часов. Фактическое время ожидания может не совпадать с заданным временем ожидания, так как указанное время ожидания будет скорректировано так, чтобы оно совпадало с тактовыми часами. Дополнительные сведения о разрешении часов и времени ожидания см. в функции спящего режима из Windows системных API.

Этот метод не выполняет стандартную перекачку COM и SendMessage.

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

7.11 – Остановки (преждевременный выход из программы)

Последняя категория инструкций управления порядком выполнения программы, которую мы рассмотрим, – это остановки. Остановка – это инструкция управления порядком выполнения программы, которая завершает программу. В C++ остановки реализованы как функции (а не как ключевые слова), поэтому наши инструкции остановки будут вызовами функций.

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

Во-первых, поскольку мы выходим из функции, все локальные переменные и параметры функции уничтожаются (как обычно).

Затем вызывается специальная функция std::exit() со значением, возвращаемым из main() (код состояния), переданным в качестве аргумента. Так что же такое std::exit() ?

Функция std::exit()

std::exit() – это функция, которая вызывает нормальное завершение программы. Нормальное завершение означает, что программа завершилась ожидаемым образом. Обратите внимание, что термин «нормальное завершение» ничего не говорит о том, была ли работа программы успешной (для этого нужен код состояния). Например, предположим, что вы пишете программу, в которой ожидаете, что пользователь введет имя файла для обработки. Если пользователь ввел недопустимое имя файла, ваша программа, вероятно, вернет ненулевой код состояния, чтобы указать на состояние сбоя, но это всё равно будет нормальное завершение.

std::exit() выполняет ряд функций очистки. Сначала уничтожаются объекты со статической продолжительностью хранения. Затем выполняется дополнительная очистка файлов, если использовались какие-либо файлы. Наконец, управление возвращается обратно в ОС, а аргумент, переданный в std::exit() , используется в качестве кода состояния.

Явный вызов std::exit()

Хотя std::exit() при завершении функции main() вызывается неявно, она также может быть вызвана явно, чтобы остановить программу до того момента, как она завершится нормально. Когда std::exit() вызывается таким образом, вам нужно будет включить заголовок cstdlib .

Вот пример явного использования std::exit() :

Эта программа печатает:

Обратите внимание, что инструкции после вызова std::exit() никогда не выполняются, потому что программа уже завершена.

Хотя в приведенной выше программе мы вызываем std::exit() из функции main() , std::exit() можно вызвать из любой функции для завершения программы в необходимой точке.

Одно важное замечание о явном вызове std::exit() : std::exit() не очищает никакие локальные переменные (ни в текущей функции, ни в функциях вверх по стеку вызовов). По этой причине обычно лучше избегать вызова std::exit() .

Предупреждение

Функция std::exit() не очищает локальные переменные в текущей функции и в функциях выше по стеку вызовов.

std::atexit

Поскольку std::exit() завершает программу немедленно, вы можете перед завершением выполнить какую-либо очистку вручную (в приведенном выше примере мы вручную вызывали функцию cleanup() ). Поэтому программисту необходимо не забывать вручную вызывать функцию очистки перед каждым вызовом exit() .

Чтобы помочь в этом, C++ предлагает функцию std::atexit() , которая позволяет вам указать функцию, которая будет автоматически вызываться при завершении программы через std::exit() .

Эта программа имеет тот же вывод, что и предыдущий пример:

Так зачем вам это делать? Это позволяет вам указать функцию очистки в одном месте (возможно, в main ), а затем не беспокоиться о том, чтобы не забыть вызвать эту функцию явно перед вызовом std::exit() .

Несколько замечаний о std::atexit() и функции очистки: во-первых, поскольку std::exit() вызывается неявно при завершении main() , если программа завершается таким образом, это вызовет любые функции, зарегистрированные std::atexit() . Во-вторых, регистрируемая функция не должна принимать никаких параметров и должна не иметь возвращаемого значения. Наконец, с помощью std::atexit() вы можете зарегистрировать несколько функций очистки, если хотите, и они будут вызываться в порядке, обратном порядку регистрации (последняя зарегистрированная будет вызываться первой).

Для продвинутых читателей

В многопоточных программах вызов std::exit() может привести к сбою вашей программы (поскольку поток, вызывающий std::exit() , будет очищать статические объекты, к которым могут обращаться другие потоки). По этой причине в C++ появилась еще одна пара функций, которые работают аналогично std::exit() и std::atexit() , – std::quick_exit() и std::at_quick_exit() . std::quick_exit() завершает программу нормально, но не очищает статические объекты и может выполнять или не выполнять другие типы очистки. std::at_quick_exit() выполняет ту же роль, что и std::atexit() для программ, завершаемых с помощью std::quick_exit() .

std::abort и std::terminate

C++ также содержит две другие функции, связанные с остановкой.

Функция std::abort() вызывает аварийное завершение вашей программы. Аварийное завершение означает, что в программе произошла какая-то необычная ошибка времени выполнения, и программа не может продолжать работу. Например, к аварийному завершению попытка разделить на 0 приведет. std::abort() не выполняет никакой очистки.

Случаи, когда std::abort вызывается неявно, мы увидим в этой главе позже (7.17 – assert и static_assert ).

Функция std::terminate() обычно используется вместе с исключениями (мы рассмотрим исключения в следующей главе). Хотя std::terminate можно вызвать явно, она чаще вызывается неявно, когда исключение не обрабатывается (и в некоторых других случаях, связанных с исключениями). По умолчанию std::terminate() вызывает std::abort() .

Когда следует использовать остановки?

Короткий ответ: «почти никогда». В C++ уничтожение локальных объектов является важной частью C++ (особенно когда мы дойдем до классов), и ни одна из вышеупомянутых функций не очищает локальные переменные. Исключения – лучший и безопасный механизм обработки ошибок.

Лучшая практика

Используйте остановки только в том случае, если нет безопасного способа нормально вернуться из функции main . Если вы не отключили исключения, используйте их для безопасной обработки ошибок.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *