Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 11

Как не зависнуть в пустом цикле for(;;)

29.01.2010, 19:55. Показов 2091. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Пишу в Visual C недавно, далеко не специалист. Часто требуется удобный интерфейс пользователя для обмена с устройствами на микроконтроллерах (моя тема), из за чего и стал осваивать Visual C. В данный момент потребовался генератор, решил использовать COM порт и написать приложение, которое бы выбирало COM порт, выставляло границы диапазона, движком или через окно редактирования задавало частоту выводимого сигнала, кнопки СТАРТ, СТОП и прочий несложный сервис. Проблема в самой функции вывода этой частоты (использую таймер высокого разрешения).
Вот её ключевой фрагмент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
QueryPerformanceFrequency( &frequency_Timer);//читаю частоту тиков
for(;;)
{
ticks=(unsigned long)(frequency_Timer.QuadPart/valid_frequency/2);//сколько тиков выждать QueryPerformanceCounter( &count0_Timer);//текущее значение таймера
do
QueryPerformanceCounter( &count1_Timer);
while(count1_Timer.QuadPart-count0_Timer.QuadPart<ticks);
//инвертируем сигнал на выходе COM порта
if(STATUS_DTR==TRUE)
{
STATUS_DTR=FALSE;
EscapeCommFunction(port,CLRDTR);
EscapeCommFunction(port,SETRTS);
}
else
{
STATUS_DTR=TRUE;
EscapeCommFunction(port,SETDTR);
EscapeCommFunction(port,CLRRTS);
}
}
Я прекрасно понимаю, что этот пустой цикл наглухо вешает всё приложение (не обрабатываются кнопки, движок задания частоты и тд). В теле цикла должно быть разрешение на обработку других событий, после чего сразу вернуться в тело цикла. Как это сделать в Visual C не знаю, но интуитивно думаю, что делается это просто (надо только знать как). Кто найдёт время и желание, подскажите, буду очень признателен. Если вместо ссылок ответите на простом языке, буду особо благодарен.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.01.2010, 19:55
Ответы с готовыми решениями:

Может ли компьютер зависнуть?
Имею собранный системник, никак немогу найти причину неполадки, тут либо БП, либо HDD. Происходит завиcание с однократным прощёлкиванием...

HP Pavilion g7 в любой момент может зависнуть
Во время работы в любой момент может произойти зависание, если немного подождать(10-60 сек) изображение на экране размазывается на...

Из-за чего может зависнуть вызов функции clearTimeout?
Добрый день. Возникла проблема с кодом, а точнее в одной из функции у меня вызывается clearTimeout, а дальше функция как бы зависает -...

9
CEO
Эксперт С++
 Аватар для Alligieri
2258 / 1248 / 57
Регистрация: 16.03.2009
Сообщений: 3,588
29.01.2010, 20:23
как вариант - запускать второй поток и в нем слушать другие сообщения и обрабатывать их. вместо for рекомендовал бы while(true) - приятнее и адекватнее смотрися просто. Если возникает така проблема - можно подумать про пересмотр самого алгоритма программы.
1
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 11
29.01.2010, 22:18  [ТС]
Про второй поток недопонимание. Программа представляет собой диалоговую панель (кнопки, окна редактирования, движок задания частоты) и текст представляет собой кучу функций - обработчиков событий (например, фрагмент кода, представленный выше, находится в функции обработки события- нажатие кнопки СТАРТ). В общем случае, в программах, которые мне приходится писать для микроконтроллеров, всегда присутствует главный (тоже пустой) цикл, в котором происходит опрос всех возможных событий и их обработка. В этот цикл я бы и вставил вывод на порт сигнала. Сдесь же (в Visual C), такого главного цикла я не нахожу. Похоже его совсем нет и сама ОС вызывает эти функции (обработчиков событий ). Вообще я не против переработать алгоритм (он не такой сложный), но я что то принципиально не понимаю. Просьба не раздражаться на мою неграмотность, и не отсылать на мудрые и толстые справочники. Я не планирую быть профессиональным программистом под Windows. Просто эту разработку хочется довести до ума самому. Заранее благодарен.
0
CEO
Эксперт С++
 Аватар для Alligieri
2258 / 1248 / 57
Регистрация: 16.03.2009
Сообщений: 3,588
29.01.2010, 22:43
Pasha_Bi, никуда вас отсылать не буду

Цитата Сообщение от Pasha_Bi Посмотреть сообщение
Сдесь же (в Visual C), такого главного цикла я не нахожу
Тем не менее он всегда есть (не главный цикл а главный поток исполнения), а если говорить про программное представление - тут всегда есть "главная" функция (которая содержит "точку входа") - int (или void) main(), int _tmain(int argc, _TCHAR* argv[]), WndProc и т.д. (зависит от типа приложения и технологии).

Добавлено через 4 минуты
Более подробно мог бы посоветовать если б видел структуру всей программы, ато даже не представляю каой у нее интерфейс
1
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 11
30.01.2010, 17:39  [ТС]
Если у Вас есть время, я бы скинул весь проект, он очень не сложный. Буду ждать адрес электронной почты, куда его переправить.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
30.01.2010, 23:18
Pasha_Bi, многопоточность юзайте. А вообще такие бесконечные циклы свидетельствуют о неправильной постановке алгоритма. Почему нельзя пользоваться таймерами? Или задержками, или ловить тики системы? Если это уже совсем никак, прийдется вручную передавать управление другим потокам.
1
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 11
31.01.2010, 19:23  [ТС]
Плоьзоваться стандартным таймером или задержкой умею, но для этого случая они не подходят, так как оперируют с милисекундами. Для меня это очень грубо. Цикл в котором я вывожу сигнал (частоту на COM порт) ловятся как раз тики системы. Сложность в том, как разрешить обрабатывать другие события, пока я жду когда "дотикают" эти системные тики.
Спасибо что откликаетесь, но хотелось бы какого нибудь конкретного кусочка программы, которая бы меня спасла.

Добавлено через 3 минуты
...прийдется вручную передавать управление другим потокам.
Вот это мне вроде и надо. Но как это сделать, не знаю. Мне бы помочь каким нибудь простеньким примерчиком.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
01.02.2010, 00:01
По многопоточности в интернете море информации. Если уж совсем никак, то помогу. Создаете новый поток, и в него записываете все эти вычисления. А потом только передаете и считываете из него параметры в форму.
Пробуйте в тот цикл засунуть
C++
1
Application::DoEvents();
Сообщение окну можно послать DispatchMessage
Попробуйте почитать о PeekMessage DispatchMessage TranslateMessage WaitForSingleObject
Я бы написал это на WinApi. Пример протой программы на С++ WinApi
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <windows.h>
#include <windowsx.h>
#include <winuser.h>
 
static char szAppName[] = "SimWnd";
void SimWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
#define BT_FIRSTBUTTON 10001
 
LRESULT CALLBACK HelloWorldWndProc(HWND,UINT,UINT,LONG);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpszCmdParam,int nCmdShow)
{
    HWND hWnd;
    WNDCLASS WndClass;
    MSG Msg;
    char szClassName[]="HelloWorld";
    WndClass.style= CS_VREDRAW|CS_HREDRAW;
    WndClass.lpfnWndProc=HelloWorldWndProc;
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
 
    WndClass.hInstance=hInstance;
    WndClass.hIcon=LoadIcon(NULL,IDI_ASTERISK);
    WndClass.hCursor=LoadCursor(NULL,IDC_HELP);
    WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.lpszMenuName=NULL;
    WndClass.lpszClassName=szClassName;
 
    if (!RegisterClass(&WndClass))
    {
    MessageBox(NULL,"Cannot register class","Error",MB_OK);
    return 0;
    }
    HRGN mw;
    GetWindowRgn(hWnd, mw);
    GetScreenWidth;
    //hWnd=CreateWindow(szClassName,"My Application",  WS_POPUP | WS_VISIBLE, mw.left,mw.left+100,mw.Top,mw.Top+100,NULL,NULL,hInstance,NULL);
    if (!hWnd)
    {
        MessageBox(NULL,"Cannot create window","Error",MB_OK);
    return 0;
    }
 
    /*SHOW YOUR WINDOW */
    RECT mr;
    GetClientRect(hWnd,&mr);
 
   CreateWindow("button", "Закрыть", WS_CHILD|WS_VISIBLE,100, 100, 80, 25, hWnd, HMENU(BT_FIRSTBUTTON), hInstance, NULL);
 
    HRGN  hgn = CreateEllipticRgnIndirect(&mr);
    HRGN  hgn2 = CreateRectRgn(200,200,220,220);
    HRGN  hgnres = CreateEllipticRgn(100,100,200,200); 
    CombineRgn(hgnres, hgn, hgn2, RGN_XOR);
    SetWindowRgn(hWnd,hgn,true);
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    /*Beginning of message cycle*/
    while (GetMessage(&Msg,NULL,0,0))
    {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
    }
    return Msg.wParam;
}
 
 
LRESULT CALLBACK HelloWorldWndProc(HWND hWnd, UINT Message,UINT wParam, LONG lParam)
{
    HDC hDC;
    PAINTSTRUCT PaintStruct;
    RECT Rect;
    HRGN  hgnelliptic;
    HRGN  hgnRectangle;
    HRGN  hgnResult=CreateEllipticRgn(100,100,200,200);;
    switch (Message) //громадный switch отлавливающий сообщения
    {
        HANDLE_MSG(hWnd, WM_COMMAND, SimWnd_OnCommand);
    case WM_SIZE:
    GetClientRect(hWnd,&Rect);
    hgnelliptic = CreateEllipticRgnIndirect(&Rect);
    hgnRectangle = CreateRectRgn(200,200,250,250);
    CombineRgn(hgnResult, hgnelliptic, hgnRectangle, RGN_XOR);
    SetWindowRgn(hWnd,hgnResult,true);      
            return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
 
 
    return DefWindowProc(hWnd,Message,wParam,lParam); 
}
    void SimWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
    {
   switch (id)
    {
        case BT_FIRSTBUTTON:
            SendMessage(hwnd,WM_CLOSE,0,0);
            MessageBox(hwnd, "Ё-моё!", "Работает,", MB_OK|MB_ICONEXCLAMATION);
            break;
    }
    }
Там есть громадный switch, который отлавливает сообщения, передающиеся окну. Попробуйте вставить туда отлавливание сообщение о тике системы и сразу после выполнения кода делать DispatchMessage. К сожалению готового кода у меня нет. И быстро его написать у меня не вышло. Самый простой способ -
C++
1
Application::DoEvent();
1
CEO
Эксперт С++
 Аватар для Alligieri
2258 / 1248 / 57
Регистрация: 16.03.2009
Сообщений: 3,588
01.02.2010, 10:02
galileopro, я тоже думал посоветовать вариант с WndProc и switch но он годится только в спайке с вторым потоком - частоту с порта ведь ловить постоянно надо.
1
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 11
06.02.2010, 19:50  [ТС]
Создал второй поток, организовал там пустой цикл while(TRUE). Выскакиваю из него при собтии из основного потока (через глобальную переменную). Всё работает. Ничего не виснет. Всем большое спасибо.
Единственный "подводный камень" - время перевода линии COM порта занимает больше времени, чем я предполагал. Так что генератор и звуковой частоты не перекрывает (<20 КГц). Думаю эту проблему не решить.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.02.2010, 19:50
Помогаю со студенческими работами здесь

Как убрать ошибку при пустом edit
Есть много эдитов,каждое поле должно быть заполнено.Надо сделать так чтоб кнопка была активна при заполнении всех эдитов. Пробовала так ,...

C# как создать таблицу в пустом файле accdb
создал в проводнике пустой файл accdb. в программе выполняю string createTableString = &quot;CREATE TABLE IF NOT EXISTS people(id INTEGER...

Как узнать тип объектов в пустом массиве
Существует массив. Необходимо узнать тип, хранящихся в нём объектов. Если массив не пустой, то это можно сделать так: return...

Как програмно в цикле не доходя до конца, пропустить шаг в цикле?
Как програмно в цикле не доходя до конца, пропустить шаг в цикле?

Как сделать чтобы не выводились данные при пустом значении WHERE
Народ, как сделать чтобы не выводились данные при пустом значении WHERE? Например:SELECT * FROM `news` WHERE `image` != 'пустое значение';


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru