Amper25
Sep 24 2008, 22:09
Собственно вопрос в теме.
Есть проект типа WindowsForm, всякие кнопочки и прочая лабуда. Проблема в следующем, при нажатии на кнопку, управление к форме возвращается только после того, как завершится выполнение функции, привязаной к данной кнопке.
Так вот если кнопкой читать какой либо большой файл или общатся по COM порту, то прога на длительные времена просто "подвисает" и перестает реагировать.
Самое простое что мне пришло на ум - это организовать чтение или обмен в другом потоке(tread). Но как это сделать я не представляю. Вообще в проекте типа формы это реально?
В данный момент все решено с помощью объекта TIMER с периодом 1мс. Процесс чтения разбивается на куски, и после каждых 2кб данных, ждем следующее переполнение. Метод конечно крайне кривой, и хотелось бы сделать как нормальные люди...
Вообщем, объясните, если не трудно что и как надо делать, или хоть направление куда идти.
PS: среда C++Bulder 6.
RSDN.ru: Работа с потоками в C# 
--
Эээээ... стоп! Какой еще WindowsForm в BCB++ 6?!

Окрывайте Google, спрашивайте "потоки с++", читайте..
DeadMoroz
Sep 24 2008, 22:59
Еще, если по-простому без тредов, можно в длительном цикле написать
Application->ProcessMessages()
тогда прога будет реагировать на другие события.
o-henry
Sep 25 2008, 06:10
Про потоки в билдере: смотри в хелпе класс TThread.
Amper25
Sep 25 2008, 13:53
Всем спасибо за ответы.
Цитата
Еще, если по-простому без тредов, можно в длительном цикле написать
Application->ProcessMessages()
тогда прога будет реагировать на другие события.
Отлично, прямо то что надо в данной ситуации. На все реагирует, только не хочет закрывать прогу почемуто.
Amper25
Sep 25 2008, 15:04
Вот еще глюки поймал.
Почему то в билдере, при добавлении(создании) класса TThread, из ClassExplorer исчезли созданные мною ранее классы. Причем они все равно используются и проект компилируется, но ClassExplorer их не видит.
Что это может быть такое?
Angelo
Sep 25 2008, 16:27
Вот статья на русском для начала, потоки и синхронизация процесов, а там дальше разберётесь я думаю... хелп от билдера посмотрите...
Syberian
Sep 26 2008, 21:15
Цитата(Amper25 @ Sep 25 2008, 17:53)

Всем спасибо за ответы.
Отлично, прямо то что надо в данной ситуации. На все реагирует, только не хочет закрывать прогу почемуто.
Чтобы оно закрыло прогу, надо выйти из процедуры. Terminate и проч. не катят. Единственный выход - вместе с ProcessMessages делать проверку глобальной переменной (типа
if (CloseFlag) {Application->Terminate; return;}), а в эвенте формы OnClose устанавливать CloseFlag в 1
Amper25
Sep 29 2008, 12:12
Angelo, спасибо за PDF-ку, очень доходчиво написано.
Возник такой вопрос:
Я создаю объект TThread, и в Execute() ему помещаю то, что должно делатся в во втором потоке.
Из этого Execute я могу посылать сообщения(Postmessage) основному окну и сообщать о текущем состоянии и пр.
Но из основного окна я не могу посылать сообщения дочернему потоку, так как объект TThread не является окном.
Что в этом случае делать? Просто объявить глобальную переменную
bool FLAG, в основном потоке писать в нее, а в дочернем постоянно читать?
Да, и как быть с ситуацией, когда запись FLAG прерывается на пол пути для переключения к другому процессу?
Использовать эмбедерские свойства volatile, или организовывать Mutex для этого флага?
MrYuran
Sep 29 2008, 12:28
Цитата(Amper25 @ Sep 29 2008, 16:12)

Но из основного окна я не могу посылать сообщения дочернему потоку, так как объект TThread не является окном.
Не совсем понятно, причём тут окно...
Если текстовые сообщения - имхо, очереди как раз для этого придумали.
Или что имеется в виду?
Amper25
Sep 29 2008, 12:35
BOOL PostMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
Проблема в этом:
HWND hWnd, // handle of destination window
Если я в качестве этого поставлю:
MY_Thread->Handle,
то компилятор ругается:
Error: Cannot convert "const unsigned int" to "void"
Потому что FORM->Handle - имеет тип void*
а TThread->Handle это просто константа типа unsigned int.
Из этого я сделал вывод, что сообщения можно посылать только окнам.
Цитата(Amper25 @ Sep 29 2008, 15:12)

Возник такой вопрос:
...
Что в этом случае делать? Просто объявить глобальную переменную
bool FLAG, в основном потоке писать в нее, а в дочернем постоянно читать?
Типа того. Только лучше не глобальную, а внутри Вашего класса-потока. И обернуть доступ к ней фунциями, обеспечивающими атомарность доступа.
Цитата
Использовать эмбедерские свойства volatile,
Не достаточно.
Цитата
или организовывать Mutex для этого флага?
Да.
Amper25
Sep 29 2008, 12:36
да и в самом определении PostMessage
HWND hWnd //handle of destination window
Тоесть только окнам.
Цитата(Amper25 @ Sep 29 2008, 16:12)

Да, и как быть с ситуацией, когда запись FLAG прерывается на пол пути для переключения к другому процессу?
Можно использовать функции Win API Interlocked... По-моему в Help'e описание присутствует.
Цитата(Asb @ Sep 29 2008, 16:18)

Можно использовать функции Win API Interlocked... По-моему в Help'e описание присутствует.
Можно. До тех пор пока sizeof(FLAG) <= 4
Цитата(Amper25 @ Sep 29 2008, 16:35)

BOOL PostMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
Проблема в этом:
HWND hWnd, // handle of destination window
Из этого я сделал вывод, что сообщения можно посылать только окнам.
Можно и не только окнам (см.
PostThreadMessage) Но учти, что бы это сообщение дошло по назначению thread, которому оно посылается, должен крутить цикл обработки сообщений (GetMessage/DispatchMessage), возникает вопрос - нафига тогда нужен такой thread?
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.