powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / А как в консольном приложении сделать таймер без при-аттаченного окна?
16 сообщений из 16, страница 1 из 1
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601184
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть консоль, есть приаттаченное "окно" hwndWindow.
15808728
Тут просто.
Код: plaintext
1.
  SetTimer(hwndWindow,NULL,500,NULL);


Но от окна я хочу избавиться.
Даже если я назначаю MyTimerProc
Код: plaintext
1.
2.
3.
4.
5.
6.
// Set the timer. 
 
SetTimer(hwnd,                // handle to main window 
    IDT_TIMER3,               // timer identifier 
    5000,                     // 5-second interval 
    (TIMERPROC) MyTimerProc); // timer callback


то окно куда он шлет WM_TIMER все равно нужно, как я понял из документации.

Даже если я оставляю окно (чисто для таймера), то мне по любому нужен цикл
Код: plaintext
1.
2.
3.
4.
5.
6.
    MSG msg;
    while( GetMessage( &msg, hwndWindow, 0, 0 ) )
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }



А main() у меня законцован на другой цикл - который проверяет mailslot через ReadFile.

Т.е. бесконечный цикл (типа со Sleep() ) позволить себе не могу, создавать новый поток не хочу,
окна тоже не хочу, а таймер хочу.
Есть тут варианты какие?
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601195
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77, я бы попробовал мультимедиа таймер .
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601224
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77main() у меня законцован на другой цикл - который проверяет mailslot через
ReadFile.

Т.е. бесконечный цикл (типа со Sleep() ) позволить себе не могу
Что мешает поставить таймаут на ReadFile и использовать его вместо Sleep()?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601280
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
выставь небольшое время ожидания ReadFile() (раз в 10-20 меньше периода таймера) и используй clock()
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
clock_t timer = clock();
int timer_step = CLOCKS_PER_SEC * 5; // 5 сек.
  for (;;)
  {
    if (ReadFile(hMailSlotHandle, buffer, 65536, &NumberOfBytesRead, NULL)!=0) {
      buffer[NumberOfBytesRead]='\0'; //отсекаем мусор
      PString str_message =  PString((LPCTSTR)buffer);
      cout << str_message << "\n";
      //обработка str_message
    }
    else {
      if(clock() > timer) {
          timer += timer_step; // если надо стабильную частоту
          // или
          timer = clock() + timer_step; // если надо равные промежутки после каждой сработки
          cout << "timeout\n";
      }
  }
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601283
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

А как в консольном приложении сделать таймер без при-аттаченного окна?

Никак, в общем-то. Но тут важно не наличие окон, а наличие цикла обработки сообщений
(GetMessage/DispatchMessage).
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601297
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЧто мешает поставить таймаут на ReadFile и использовать его вместо Sleep()?

Ну, идея то вообщем неплохая.
Единственная тонкость: ReadFile может выйти 1) по таймауту 2) по приему сообщения
Т.е. возникает вопрос, 1)отрабатывать ли оба варианта или 2)только по таймауту
Если оба, то при частых сообщениях "таймер" будет срабатывать чаще.
Если только по таймауту, то при частых сообщениях он будет не срабатывать.
Т.е. по любому не гарантируется стабильный интервал между тиками.

Если смотреть на логику, то основная логика такова:
Другое приложение через message присылает "задание". Задание кладется в "буфер". Таймер проверяет наличие задания в буфере и возможность начать его выполнять. Если выполняются оба условия, то задание начинает выполняться, "буфер" очищается, а другому приложению отправляется ответ "задание пошло в работу, можешь присылать следующее". Т.е. по логике программы в "буфере" всегда находится одно задание.
Ну, при данной логике разумно "отрабатывать оба варианта" (исключает паузу между сообщением и "тиком таймера" -т.е. задание сразу отправляется в работу при наличии возможностей сразу начать его выполнять).

Хорошая идея. Но надо продумывать, таймер еще кое-какие задачи отрабатывает.

А с другой стороны, если я использую таймер, то нафига мне ловить задание "как только так сразу" (сыр бор предыдущего топика), если все равно они не пойдут в работу раньше чем тикнет таймер. Ну в таймере бы и читал mailslot своим стандартным способом.

Вот эту логику с заданиями я так и не могу до ума довести. В итоге все всегда упирается в "невозможность запустить более определенного числа заданий в единицу времени". Либо надо делать долбеж с низкими интервалами, либо получаем ограничение "интервалами таймеров" на той и другой стороне. Т.е. клиент не посылает след. задание пока не получил от сервера подтверждение принятия предыдущего.

Можно класть по несколько заданий в буфер сервера (принцип очереди на стороне сервера), но это сильно усложнит логику. Пытался как-то, плюнул.
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601312
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Если смотреть на логику, то основная логика такова:
Странная логика. Если пришло сообщение, его надо получить и обработать сразу. Если таймер
"делает что-то ещё", то пусть и делает это "что-то ещё", а в обработку сообщений вообще не
суётся. Не надо мешать мухи с котлетами.

PS: И таки да, в этом случае вместо Sleep() лучше использовать GetMailslotInfo() на
котором ты так настаивал.
PPS: Никто не мешает тебе передавать ему не фиксированный таймаут, а вычислять его каждый
раз как остаток от необходимого интервала, получая таким образом совершенно равномерные
"тики" "таймера".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601325
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати уповать на SetTimer() тоже не следует. SetTimer() ставит в очередь сообщений событие WM_TIMER с заданной периодичностью, оно может накопиться в очереди сообщений и потом залпом выпасть на обработку, и вместо 10 раз каждые 100 мс получишь спустя 1000 мс непрерывный поток 10 раз подряд.
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601327
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНикак, в общем-тоне совсем так

CreateWaitableTimer

для выполнения Completion routine (как и для асихронного ввода-вывода) нужен переход в alertable wait state (SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx, or WaitForSingleObjectEx)
что впрочем можно считать неким аналогом цикла обработки сообщений
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601331
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

это другой таймер.
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601335
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivИзопропил,

это другой таймер.
конечно другой
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601360
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovДмитрий77Если смотреть на логику, то основная логика такова:
Странная логика. Если пришло сообщение, его надо получить и обработать сразу.

А что тут странного. Пришло, да, обработал сразу -сунул в "буфер".
А задание в сообщении: сделать телефонный звонок.
Чтобы звонок сделать, нужна свободная линия.
Если она есть, то логично сразу и звонить.
Если нет, то таймером проверять, не появилась ли, и если появилась, то звонить.

Я конечно могу клиентом спрашивать "А есть ли свободная линия?" Но это лишнее сообщение серверу и лишний ответ клиенту = потерянное время (на VB-клиенте я без таймера не обойдусь). Плюс это еще долбеж сервера клиентом.

Мне проще слепо сунуть "первое задание из очереди" в "буфер" C++ сервера, и на клиенте ждать пока оно "пойдет в работу" (по обратному сообщению от сервера).

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

Собственно, описанное выше - это основная часть работы конструкции.

По поводу "сообщений другого вида".
Они достаточно редки. Например клиент делает некий общий запрос к серверу раз в 10 секунд.
Ну, будет таймер изредка срабатывать "чуть быстрее", можно и ничего не делать, каши маслом не испортишь.

По поводу "Если таймер делает что-то ещё",
по сути ничего, проверяет наличие текстового файла с сообщением "STOP" -грамотное завершение приложения, чтоб вывести main() из for(;;) -то в чем меня обвинили с ресурсами при выходе - какую-то часть работы я считаю-таки необходимым делать (не совсем "taskkill").
Но по сути эту фигню можно заменить на "сообщение" -не делал этого с SendMessage, т.к. SendMessage не шлет сообщения из под юзера в LocalSystem. А mailslot-у пофиг, в этом кстати еще одно преимущество.

Не, по хорошему мне бы этого "VB-клиента" вообще выкинуть (GUI-морды у него кстати нет), а то что он делает вставить в код С++ сервера.
Тогда логика сильно упростится.
Но это блин счас начнется изучение C++ на 3 месяца вперед: а как работать с БД из C++, а как добавить модуль, а как проконвертировать LPSTR в LPPPSCTRRSTR. А как передавать данные из dll-плагина в основной exe и т.п. (потому что я честно говоря мухлюю местами, т.е. например скидываю статистику - через Sendmessage/mailslot и из C++ exe, и из основного С++dll и из C++ dll плагина а VB-клиент все это собирает и обрабатывает "в одном окне") Оно мне честно желания нету.
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601399
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А main() у меня законцован на другой цикл - который проверяет mailslot через ReadFile.

Т.е. бесконечный цикл (типа со Sleep() ) позволить себе не могу, создавать новый поток не хочу,
окна тоже не хочу, а таймер хочу.
Есть тут варианты какие?

вот и дошли до ожидания нескольких событий

запускаем асинхронное чтение из мейлслота, в цикле крутим SleepEx например
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38601471
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

ты мой пример с clock() выше заметил? Так хоть десять таймеров ставь в else.
По-хорошему, для повышения точности, перед ReadFile() вычислить время до сработки таймера и задать через SetMailslotInfo()
примерно так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
clock_t timer = clock();
int timer_step = CLOCKS_PER_SEC * 5; // интервал сработки таймера, 5 сек.
  for (;;)
  {
    int timeout = (clock() - timer) / (CLOCKS_PER_SEC / 1000) + 1; // время до сработки таймера, мс
    if(timeout < 0) {
       timeout = 0;
    }
    SetMailslotInfo(hMailSlotHandle, timeout);
    if (ReadFile(hMailSlotHandle, buffer, 65536, &NumberOfBytesRead, NULL)!=0) {
      ... //обработка сообщения
    }
    else {
      if(clock() > timer) { // проверка сработки таймера
          timer += clock() + timer_step; // установка времени следующей сработки таймера
          ... // полезный код таймера
      }
  }


Если компилятор только от MS и другими пользоваться не планируешь, то c CLOCKS_PER_SEC можешь не заморачиваться, MS гарантирует что clock() дает время в миллисекундах как минимум начиная с MSVC2005 , т.е. CLOCKS_PER_SEC = 1000
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38602129
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tты мой пример с clock() выше заметил?
Дим, заметил. И идею понял.
Но в данном случае мне "неравномерный таймер" на руку. Т.е. "тикать" и по приходу сообщения, и по таймауту. Почему я написал выше.

Т.е. ценных идей из этих моих 2 топиков я почерпнул 2:
1) "Как только так сразу"
Вешаться через ReadFile на mailslot (с бесконечным в идеале таймаутом для mailslot)
2) "Таймер"
Использовать "код таймера" в цикле ReadFile (с конечным таймаутом для mailslot который есть интервал таймера). Ну, да, при необходимости точности твой код.

Вроде все сделал чего хотел. Заменил SendMessage-ы на mailslot-ы по всему проекту, убрал приаттаченное окно. Результаты тестов как бы меня устроили, отдал файлы двоим клиентам на "продакшн-тестирование".

На самом деле по хорошему "таймер" вообще можно (надо?) убрать.
Достаточно двух действий.
1) При получении "сообщения" с заданием сразу проверять условие (наличие свободной линии) Если есть - выполнять, если нет - класть в "буфер".
2) При возникновении "условия" (событие завершения очередного телефонного вызова) проверять "буфер" и если есть задание, сразу его выполнять.

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

А "CALLBACK-ов" в данном случае 2: пункты (1) и (2) что выше.
Нечто подобное я реализовывал с внутренней очередью сообщений в трей:

А как грамотно организовать "очередь сообщений"
...
Рейтинг: 0 / 0
А как в консольном приложении сделать таймер без при-аттаченного окна?
    #38602304
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77При необходимости использовать принцип очереди (плавающий буфер) -если сразу буферизовать много заданий (я буферизую одно).
Кладем задание в конец массива
Берем задание в работу из первого элемента, элементы сдвигаем, крайний удаляем.
В STL есть класс queue реализующий очередь. тут пример использования
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / А как в консольном приложении сделать таймер без при-аттаченного окна?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]