Выдержать "паузу" в приложении.

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Выдержать "паузу" в приложении.

Re: Выдержать "паузу" в приложении.

BBB » 25 сен 2007, 12:38

Hawk писал(а):А тебе так нужен callback? Исходя из твоей задачи он тебе не нужен совсем. А callback можно сделать и обычным SetTimer если так надо.
Мне хотелось бы "поспать" какой-то промежуток времени, выждать некоторый тайм-аут, (причем поспать "асинхронно", т.е. чтобы приложение в этот момент не "умирало", реагировало на другие "внешние воздействия"), после которого сделать нужные действия. Callback - это как вариант (поскольку именно callback имеется в WaitableTimer).
Обычный SetTimer - это тоже вариант, но меня несколько смущало (см. самое первое мое сообщение в этой теме), что если такие ситуации (т.е. необходимость выдерживать тайм-ауты) будут повторяться в программе часто, то придется часто делать SetTimer и (после истечения тайм-аута) KillTimer. Смущало, не есть ли плохо (для Windows, ресурсов или еще-чего-нибудь) такое постоянное "дергание" (установка/"убийство") виндовых таймеров.

Re: Выдержать "паузу" в приложении.

Hawk » 25 сен 2007, 12:10

А тебе так нужен callback? Исходя из твоей задачи он тебе не нужен совсем. А callback можно сделать и обычным SetTimer если так надо.

Re: Выдержать "паузу" в приложении.

BBB » 25 сен 2007, 11:57

WinMain писал(а):Удобнее использовать не голые Win32API-функции, а применить класс-обёртку на С++. Набери в поисковике что-нибудь типа "CWaitableTimer".
WinMain, Hawk,
я вот тоже, глядя на найденные примеры (как в MSDN, так и в интернете), вижу, что после запуска таймера тем или иным способом запускается "остановка (ожидание)" в денной точке. Без этого, похоже, не будет вызванна указанная callback-процедура. (Кстати, в большинство примеров вызов SetWaitableTimer происходит без указания callback-процедуры).

Например, в одном из примеров (MFC-dialog-based-приложения) таймер запускается при нажатии на кнопку окна. Т.е., стало быть (если копать "вглубь"), внутри оконной пр-ры-обработчика событий. И далее тут же стоит:

SleepEx (INFINITE, TRUE);

Callback-функция (указанная в SetWaitableTimer) вызывается, после чего SleepEx возвращает управление.

Убираю этот SleepEx (т.е. получаем, что программа покидает оконную пр-ру-обработчик до истечения указанного таймеру времени) - callback-пр-ра уже не вызывается!

Re: Выдержать "паузу" в приложении.

Hawk » 24 сен 2007, 13:07

WaitableTimer по тому и Waitable, что предполагается его ждать функциями WaitFor..Object(s). А данном случае никакого смысла его использовать нету. Проще обычным Sleep или теми же Wait... с таймаутом необходимым - результат будет такой же. А именно блокировка потока до истечения какого-то времени. Если не хочется блокировать поток, то без цикла обработки сообщений не обойтись.
Но кстати тут и может пригодиться WaitableTimer чтобы ждать его в MsgWaitFor...
Вот пример из MSDN цикла сообщений с ожиданием событий

Код: Выделить всё

int MessageLoop ( 
    HANDLE* lphObjects,  // handles that need to be waited on 
    int     cObjects     // number of handles to wait on 
  )
{ 
    // The message loop lasts until we get a WM_QUIT message,
    // upon which we shall return from the function.
    while (TRUE)
    {
        // block-local variable 
        DWORD result ; 
        MSG msg ; 

        // Read all of the messages in this next loop, 
        // removing each message as we read it.
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            // If it is a quit message, exit.
            if (msg.message == WM_QUIT)  
                return 1; 
            // Otherwise, dispatch the message.
            DispatchMessage(&msg); 
        } // End of PeekMessage while loop.

        // Wait for any message sent or posted to this queue 
        // or for one of the passed handles be set to signaled.
        result = MsgWaitForMultipleObjects(cObjects, lphObjects, 
                 FALSE, INFINITE, QS_ALLINPUT); 

        // The result tells us the type of event we have.
        if (result == (WAIT_OBJECT_0 + cObjects))
        {
            // New messages have arrived. 
            // Continue to the top of the always while loop to 
            // dispatch them and resume waiting.
            continue;
        } 
        else 
        { 
            // One of the handles became signaled. 
            DoStuff (result - WAIT_OBJECT_0) ; 
        } // End of else clause.
    } // End of the always while loop. 
} // End of function.

Можно создать WaitableTimer на 15 секунд например и передать его в эту функцию -
MessageLoop(&hTimer, 1); и она будет крутить цикл сообщений пока не пройдет 15 секунд (правда тогда "DoStuff (result - WAIT_OBJECT_0) ;" надо на "return" наверно заменить )

Re: Выдержать "паузу" в приложении.

WinMain » 22 сен 2007, 23:17

Удобнее использовать не голые Win32API-функции, а применить класс-обёртку на С++. Набери в поисковике что-нибудь типа "CWaitableTimer".

Re: Выдержать "паузу" в приложении.

BBB » 21 сен 2007, 19:13

Попробовал с WaitableTimer, что-то не получается.

Написал с вызовом callback-функции:

SetWaitableTimer (hTimer, &tm, 0,
MyCompletionRoutine, // completion routine
&MyArgToCompletionRoutine, // completion routine parameter
0);

Нифига она не вызывается :(
Интервал ставил 15 секунд:

tm.QuadPart = -150000000;

Насторожила строка в MSDN:

The completion routine is executed by the thread that activates the timer using SetWaitableTimer. However, the thread must be in an alertable state.

Может, в данном случае этого "стейта" и нет...

Re: Выдержать "паузу" в приложении.

BBB » 21 сен 2007, 14:41

WinMain писал(а):Есть ещё в системе так называемый Waitable Timer. Соответственно, функции для него CreateWaitableTimer() и SetWaitableTimer().
По-моему, это как раз то, что тебе нужно.
Правильно ли я понимаю, что последовательность действий примерно такая:

hTimer = CreateWaitableTimer (NULL, TRUE, NULL); // или 3-й п-ер какое-нибудь имя

Далее, в момент начала паузы:

SetWaitableTimer (hTimer, <интервал_паузы>, 0,
MyCompletionRoutine, // completion routine
&MyArgToCompletionRoutine, // completion routine parameter
0);

По истечении указанного промежутка вызовется MyCompletionRoutine.
А отменить таймер (если до истечения указанного промежутка выясниться, что он уже не актуален):

CancelWaitableTimer (hTimer);

Далее по необходимости возможны повторные вызовы SetWaitableTimer.

Так?

Re: Выдержать "паузу" в приложении.

BBB » 21 сен 2007, 14:34

Absurd писал(а):В прямом смысле: пока на экраме модальный диалог, приложение заблокировано до тех пор пока оно (т.е модальное окно) не закроется. Следовательно, надо не размещать на модальном диалоге конпки "Закрыть" и рисовать прогресс-бар чтобы юзверь не думал что программа повисла.
Да это вообще предполагается программа, которая без участия пользователя "в автономе" должна работать :)

Re: Выдержать "паузу" в приложении.

Absurd » 21 сен 2007, 13:42

BBB писал(а):То есть?
В прямом смысле: пока на экраме модальный диалог, приложение заблокировано до тех пор пока оно (т.е модальное окно) не закроется. Следовательно, надо не размещать на модальном диалоге конпки "Закрыть" и рисовать прогресс-бар чтобы юзверь не думал что программа повисла.

Re: Выдержать "паузу" в приложении.

WinMain » 21 сен 2007, 12:35

Есть ещё в системе так называемый Waitable Timer. Соответственно, функции для него CreateWaitableTimer() и SetWaitableTimer().
По-моему, это как раз то, что тебе нужно.

Вернуться к началу