Задачи таймера предназначены для ожидания определённого времени без использования потока. Уведомление о завершении таймера осуществляется через коллбэк.
Класс WFTaskFactory
включает четыре метода, связанных с таймерами:
using timer_callback_t = std::function<void (WFTimerTask *)>;
class WFTaskFactory
{
...
public:
static WFTimerTask *create_timer_task(time_t seconds, long nanoseconds,
timer_callback_t callback);
static WFTimerTask *create_timer_task(const std::string& timer_name,
time_t seconds, long nanoseconds,
timer_callback_t callback);
static int cancel_by_name(const std::string& timer_name)
{
cancel_by_name(const std::string& timer_name, (size_t)-1);
}
static int cancel_by_name(const std::string& timer_name, size_t max);
};
Для создания задачи таймера используются два параметра: seconds
и nanoseconds
, которые указывают время ожидания.
seconds
может принимать значение -1
, что создаст бесконечный таймер, обычно используемый для названных таймеров, чтобы иметь возможность отменить его позже.nanoseconds
должно находиться в диапазоне [0, 1000000000)
. В противном случае, после запуска таймера будет немедленно возращена ошибка с кодом EINVAL
.При создании задачи таймера можно передать имя таймера (timer_name
). Это имя используется для отмены задачи таймера через метод cancel_by_name
.
Задачи таймера также являются типом задачи, поэтому они могут использоваться так же, как и другие типы задач. Они имеют поле user_data
, которое можно использовать для хранения данных пользователя.
Если при создании задачи таймера было указано имя, то эту задачу можно отменить до её выполнения.
Отмена задачи таймера выполняется через метод WFTaskFactory::cancel_by_name
. По умолчанию этот метод отменяет все задачи таймера с данным именем. Однако, вы можете передать параметр max
, который ограничит количество отмененных задач.
Пример программы, демонстрирующей использование задачи таймера:
#include <stdio.h>
#include "workflow/WFTaskFactory.h"
int main()
{
WFTimerTask *timer = WFTaskFactory::create_timer_task("test", 10000, 0, [](WFTimerTask *){
printf("таймер вызван обратно, состояние = %d, ошибка = %d.\n", task->get_state(), task->get_error());
});
WFTaskFactory::cancel_by_name("test");
timer->start();
getchar();
return 0;
}
Программа сразу выводит сообщение 'таймер вызван обратно, состояние = 1, ошибка = 125.'
, поскольку задача была отменена до начала выполнения. Поэтому, если задача таймера была отменена до запуска, она немедленно вызывает обратный коллбэк, состояние равно WFT_STATE_SYS_ERROR
, а код ошибки равен ECANCELED
.
Необходимо отметить, что использование названных таймеров требует больше затрат по сравнению с анонимными таймерами, поскольку требуется поддерживать таблицу поиска и выполнять операции блокировки/разблокировки. Если нет необходимости отменять таймер заранее, лучше не указывать имя при создании задачи таймера.
Как описано в разделе О выходе программы, когда основной метод завершён или вызван exit()
, все задачи должны завершиться и вызвать обратные коллбэки. При этом новые задачи не должны быть запущены.
Это может привести к проблеме, если период таймера очень велик. В этом случае, если таймер не может быть прерван, программа может долго ждать завершения таймера перед тем, как завершиться.
На практике, выход программы может прервать задачу таймера, заставив её вернуться к обратному коллбэку. Если задача таймера была прервана выходом программы, get_state()
вернет состояние WFT_STATE_ABORTED
.
Ниже представлен пример программы, которая каждую секунду получает HTTP страницу. Когда все URL были обработаны, программа завершается немедленно, без ожидания завершения задачи таймера.
bool program_terminate = false;
void timer_callback(WFTimerTask *timer)
{
mutex.lock();
if (!program_terminate)
{
WFHttpTask *task;
if (urls_to_fetch > 0)
{
task = WFTaskFactory::create_http_task(...);
series_of(timer)->push_back(task);
}
series_of(timer)->push_back(WFTaskFactory::create_timer_task(1, 0, timer_callback));
}
mutex.unlock();
}
...
int main()
{
...
/* все URL обработаны */
mutex.lock();
program_terminate = true;
mutex.unlock();
return 0;
}
В данном примере, метод timer_callback
должен проверять условие program_terminate
внутри блокировки, чтобы избежать запуска новых задач после завершения программы.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )