Форум программистов, компьютерный форум, киберфорум
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
1

Как сделать, чтоб окно одновременно принимало сообщения и выполнялась какая-нибудь ф-ция

05.01.2011, 14:27. Показов 2446. Ответов 20
Метки нет (Все метки)

Опыт работы с "окнами" совсем небольшой (примеры из книг), вот решил сам попробовать. Сначала была консольная прога, все работало, решил прикрутить ее к окну Windows, написал маленькое окошко с кнопками "начать", "пауза" и "выход", и сталкнулся с такой проблемой - при нажатии кнопки "начать" запускается ф-ция (которая была главной в консольной проге) и пока эта ф-ция работает (1-2 минуты), окно не принимает сообщения, жму на "пауза" и ничего, при чем если понажимать на кнопки "пауза" и "выход", то после звершения этой ф-ции окно подвисает. Потом сделал так, через каждую строчку кода в этой ф-ции (которая 1-2 мин. работает) вставил такие строки:
C++
1
2
GetMessage(&Msg,NULL,0,0);
DispatchMessage (&Msg) ;
чтоб окно постоянно обрабатывало сообщения, но во первых - это лютый быдлокод, во вторых все равно глючит.
Вопрос - как решить подобную проблему? Желательно без второго потока)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.01.2011, 14:27
Ответы с готовыми решениями:

как сделать чтоб функция выполнялась пока зажата ЛКМ?
Есть макрос наподобие этого: mouse_event((0x0001), -1, 3, 0, 0); Sleep(11);...

как сделать чтоб команда выполнялась через некоторое время?
все в заголовке:)

Как сделать,чтоб после выполнения программа выполнялась заново и считывала значения уже с другого файла
#include "stdafx.h" #include "algorithm" // для min, max #include "iostream" #include...

Как выставить правило валидации,чтоб принимало число только с точкой?
Нужно прописать правило валидации чтоб принимало число только с точкой. Например чтоб принимало...

20
33 / 33 / 2
Регистрация: 24.09.2010
Сообщений: 140
05.01.2011, 15:39 2
Обычно в цикл функции которая долго работает вставляется типо
while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
ещё посмотри Examining a Message Queue
1
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 15:47  [ТС] 3
Я что-то похожее сделал, понавставлял:
C++
1
2
3
4
if(PeekMessage(&Msg,NULL,0,0,PM_NOREMOVE)){
    GetMessage(&Msg,NULL,0,0);
    DispatchMessage (&Msg) ;
    }
Попробую как ты показал, так за раз больше сообщений удалится из очереди, меньше вероятность подвисания, как мне кажется.

Цитата Сообщение от Nwq Посмотреть сообщение
ещё посмотри Examining a Message Queue
С английским совсем туго( Поищу что-нибудь по-русски на эту тему.
0
Почетный модератор
Эксперт .NET
8692 / 3644 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
05.01.2011, 15:52 4
Kastaneda, при долгих вычисления, которые могут прервать поток сообщений GUI, обычно создают новый поток. Я думаю с этим будет меньше проблем.
0
Заблокирован
05.01.2011, 16:01 5
попробуйте вставить в цикл
C#
1
Application.DoEvents();
0
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 16:09  [ТС] 6
SSTREGG, да вот проблема в том, что я этого ни когда не пробовал, похоже придется.
Dzhej-Dzhej, сейчас почитаю, что это такое)

Добавлено через 23 секунды
Nwq, да, глюков меньше стало)

Добавлено через 6 минут
Dzhej-Dzhej, похоже это из области "программирования мышкой", на WinAPI такого нет. (если верить гуглу))
0
Заблокирован
05.01.2011, 16:14 7
Kastaneda, извиняюсь, не заметил, что С++
(функция для .net)
0
Kastaneda
05.01.2011, 16:16  [ТС]
  #8

Не по теме:

Цитата Сообщение от Dzhej-Dzhej Посмотреть сообщение
Kastaneda, извиняюсь, не заметил, что С++
Да это я не сказал, что на С++, забыл))

0
Почетный модератор
Эксперт .NET
8692 / 3644 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
05.01.2011, 16:20 9
Kastaneda, да там разбираться даже не надо функция CreateThread:
C++
1
2
3
4
5
6
7
8
9
10
DWORD WINAPI        ThreadProc(LPVOID);
...
CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); /* Вызывай там где раньше выполнялось действие.
Лучше конечно прочитать, за что отвечает каждый параметр, и обрабатывать возможные неблагоприятные последствия */
...
DWORD WINAPI ThreadProc(LPVOID param)
{
    // Здесь выполнение времязатратного действия
    return 0;
}
В реальной ситуации надо только синхронизацию немного продумать.
0
Evg
Эксперт CАвтор FAQ
21160 / 8176 / 628
Регистрация: 30.03.2009
Сообщений: 22,475
Записей в блоге: 30
05.01.2011, 16:24 10
Цитата Сообщение от Kastaneda Посмотреть сообщение
Желательно без второго потока)
Присоединяюсь к мнению, что проще работать через поток. При подходе, описанном в первом посте, программа выполняет дополнительные телодвижения, из-за которых всё-равно будет визуальное подлагивание гуя (во всяком случае, у меня было именно так), да и не всегда понятно, в каких местах надо вставлять такой код, чтобы он исполнялся с более-менее равномерными интервалами. А если создать поток, то весь геморрой ляжет на ОС (которая с этим справится гораздо лучше). Правда на программиста возлагается другой геморрой, связанный с синхронизацией. После исследований методом тыка я остановился на варианте именно с потоками. Правда это было в Borland'овском VCL, а не WinAPI, но принципиальной разницы нет. Геморрой заключался только в том, что надо разобраться с предметом и написать простенькую библиотеку поддержки
0
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 16:26  [ТС] 11
SSTREGG, наверно придеться. А что вы подразумеваете под синхронизацией? Я с потоками вообще не знаком.
0
Почетный модератор
Эксперт .NET
8692 / 3644 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
05.01.2011, 16:37 12
Цитата Сообщение от Kastaneda Посмотреть сообщение
А что вы подразумеваете под синхронизацией?
Если у Вас в том методе использовались какие-либо данные, которые могут быть использованы в нескольких местах (методах, потоках) одновременно, то обычно для таких данных использую синхронизацию, дабы избежать беспорядочного обращения к этим данным, и всё делать синхронно (совместно) но при этом не нарушая порядка.

Для этой цели вполне могут подойди критические секции [MSDN]. К тому же вот [MSDN] описание возможных синхронизаций потоков.
1
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 16:58  [ТС] 13
Буду разбираться)
0
Evg
Эксперт CАвтор FAQ
21160 / 8176 / 628
Регистрация: 30.03.2009
Сообщений: 22,475
Записей в блоге: 30
05.01.2011, 17:48 14
Ещё тут была долгая бодяга с синхронизацией
Вопрос по работе WaitForSingleObject
1
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 18:35  [ТС] 15
На сколько я понял, если у меня созданный поток будет работать с одной глобальной переменной (bool PAUSE), то мне ни какая синхронизация не нужна. Созданный поток будет только проверять значение переменно, менять ее он не будет.
И еще вопрос, когда в ф-цию главного окна (оно же единственное) будет послано сообщение WM_DESTROY, вызовется PostQuitMessage(0), я так понимаю, что при этом закроются все потоки, связанные с процессом, т.е. самостоятельно мне созданный поток зарывать не надо?

Добавлено через 24 минуты
А может кто-нибудь подскажет, как поток остановить, а потом заново (а не с места остановки) начать?
0
Evg
Эксперт CАвтор FAQ
21160 / 8176 / 628
Регистрация: 30.03.2009
Сообщений: 22,475
Записей в блоге: 30
05.01.2011, 19:07 16
Цитата Сообщение от Kastaneda Посмотреть сообщение
На сколько я понял, если у меня созданный поток будет работать с одной глобальной переменной (bool PAUSE), то мне ни какая синхронизация не нужна. Созданный поток будет только проверять значение переменно, менять ее он не будет.
Теоретически да. Но если, грубо говоря, проверка идёт в цикле типа "while (var) { ... }", а тело цикла не содержит операций вызова, то переменную var надо пометить признаком volatile, чтобы компилятор знал, что в данном случае есть "невидимое для компилятора" средство модификации переменной, и не делал оптимизаций над ней

Цитата Сообщение от Kastaneda Посмотреть сообщение
И еще вопрос, когда в ф-цию главного окна (оно же единственное) будет послано сообщение WM_DESTROY, вызовется PostQuitMessage(0), я так понимаю, что при этом закроются все потоки, связанные с процессом, т.е. самостоятельно мне созданный поток зарывать не надо?
Посмотри Прибить программу, находясь в потоке
Там полезные ссылки

Цитата Сообщение от Kastaneda Посмотреть сообщение
А может кто-нибудь подскажет, как поток остановить, а потом заново (а не с места остановки) начать?
Мне кажется, что такого средства нет. Потому как нужно убить поток и запустить его заново. Это задача пользовательского уровня и навряд ли ОС будет какие-то интерфейсы для этого предоставлять
1
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 20:40  [ТС] 17
Скажите, корректно ли будет сделать так:
C++
1
2
3
4
5
6
7
DWORD WINAPI ThreadProc(LPVOID){
   while(true){
      if(!PAUSE)
         MyFunc();
   }
   return 0;
}
а когда плученно сообщение WM_DESTROY от главного окна, то вызывается такая ф-ция
C++
1
2
3
4
5
6
7
void OnDestroy(HWND,HANDLE T){//Т - это хендл потока
    DWORD ExitCode;
    GetExitCodeThread(T,&ExitCode);
    ExitThread(ExitCode);
    PostQuitMessage(0);
    //exit(0);
}
Завершится ли так созданный поток, ведь там вызов ф-ции в вечном цикле?
0
Evg
Эксперт CАвтор FAQ
21160 / 8176 / 628
Регистрация: 30.03.2009
Сообщений: 22,475
Записей в блоге: 30
05.01.2011, 20:49 18
Если OnDestroy предполагается выполнять в потоке, то вроде бы как нет. Сообщение - это всё-таки не сигнал. Чтобы его обработать, поток должен сделать некие телодвижения (залезть в очередь сообщений). Из главного процесса поток можно просто убить (или тебе важно, чтобы поток знал, что его убивают?)
0
Jesus loves me
Эксперт С++
5164 / 3137 / 353
Регистрация: 12.12.2009
Сообщений: 7,925
Записей в блоге: 2
05.01.2011, 21:11  [ТС] 19
Если OnDestroy предполагается выполнять в потоке
Нет, не в потоке. OnDestroy вызывается из оконной процедуры главного окна.
(или тебе важно, чтобы поток знал, что его убивают?)
Нет, не важно. Попробовал сделать, как показал выше, окно закрывается (т.е. OnDestroy вызывается), а поток продолжает работать. А нужно,чтоб при закрытии окна (т.е. программы), поток убивался. Не могу сделать(

Добавлено через 3 минуты
Проблему решил, вместо:
C++
1
ExitThread(ExitCode);
нужно:
C++
1
TerminateThread(T,ExitCode);
0
33 / 33 / 2
Регистрация: 24.09.2010
Сообщений: 140
06.01.2011, 00:34 20
Перед выходом из программы нужно дождаться завершения потока:
hThread = CreateThread(...);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.01.2011, 00:34

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

CommandField: после действия в этом поле окно закрывается, как сделать чтоб окно оставалось открытым
Использую jquery чтоб открыть диалоговое окно по ссылке, в открываемом окне добавил GridView в нем...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.