C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Простейший Thread, Простейшая многопоточная программа
Steam-x
  Отправлено: 11.06.2004, 10:56


Дежурный стрелочник

Группа: Участник
Сообщений: 60



Привет Всем!
Люди добрые, помогите, кто чем может. Кто добрым словом, кто советом полезным, а кто и просто вниманием. smile.gif
Вот какая проблема. Мне нужно забабахать много поточную программу. Залез в Хелп по Thread, но там не хре... (ой чуть не написал — не хрена) ничего не понятно. Залез в ФАКи по стройке, но там длиннющий пример с поисками файлов. А мне бы простейший пример. Ну типа такого:
Форма с двумя Батонами. Давишь первый запускается отдельный поток, ну допустим просто плюсуется переменная и выводится в Лабел.
Давишь вторую кнопель, и все, кирдык процессу.
А в это время на основной форме неустанно фигасится текущее время, не зависимо выполняется ли второй поток или уже прибит.
И если возможно с коментариями, что зачем и почему делается.
Заранее благодарен, хотя бы за то, что Вы дочитали до этих строк.
Roman
Отправлено: 11.06.2004, 13:06


Дежурный стрелочник

Группа: Участник
Сообщений: 78



А раздел "Уроки" на сайте для кого?

Смотри
Урок 2 — Многопоточное приложение

Отредактировано Roman — 11/06/2004, 14:09
exp
Отправлено: 12.06.2004, 00:26


Мастер участка

Группа: Участник
Сообщений: 304



Вот что получилось. Использовал ссылку. Мой первый работающий поток. smile.gif

User Attached Image Скачать файл
Threads.zip


Guest
Отправлено: 12.06.2004, 01:14


Не зарегистрирован







TThread в некоторых случаях очень скользкая штука. С ним нельзя обращаться как с обычным классом или компонентом. Некоторые действия с ним уникальны и не имеют аналогов. Посему, надо уяснить все нюансы на ключевых этапах: создание, управление, обмен данными, удаление. Повторю — все уникально и ничего не делай, если не знаешь, как это делается именно в TThread!
1 Создание. File->New->Thread Object. Даем имя THREAD. Сохраняем Unit как THREAD.cpp. Объявлем указатель на объект в файле заголовка Form1 в разделе public: class THREAD *thread ; Подключаем файл “THREAD.h” во все .cpp файлы проета, где нужен thread. Создаем объект:
thread->FreeOnTerminate=true; /* если остаются данные в объекте то можно false;*/
thread->OnTerminate = threadend ; /* функция вызываемая сразу после разрушения объекта
Объявление: void __fastcall threadend (TObject *Sender); необязательно */
thread->Priority = tpIdle; /* рекомендуется; необязательно*/
thread = new THREAD (false) ; /* создаем и сразу запускаем. Если true, то объект Suspended , то есть остановлен */
2 Управление. Вся работа идет внутри единственной функции Execute(). Выход из этой функции означает разрушение объекта (если FreeOnTerminate=true). Поэтому включаем цикл:

#include “Form1.h”
void __fastcall THREAD::Execute()
{
while ( !Terminated ) /* Terminated- приватный член класса TThread */
{
/* здесь весь код для работы */
SendMessage ( Form1->Handle , ThMessage1 , 0 , 0 ) ;
}

exit: /* переход на эту метку означает выход и разрушение объекта*/
};

Объект может быть в двух состояниях: Suspended == true (остановлен) и ==false (работает). Изнутри он может сам себя остановить: Suspend() или Suspended = true ; а вот запустить — никак. Внешнее управление: остановка thread->Suspend(), запуск thread->Resume(). ОСТОРОЖНО!!! — Suspend() увеличивает внутренний счетчик на 1, а Resume() уменьшает на 1. Если дважды вызвать Suspend() и потом один раз Resume(), то объект останется неработающим!!! Поэтому, если надо обязательно запустить:
while ( thread->Suspended ) thread->Resume();

3. Обмен данными. Самое сложное в TThread. Нельзя изменять свойства компонентов напрямую из thread (хотя есть исключения, но лучше не рисковать)!!! И даже обращаясь к переменным и массивам в главной форме надо помнить о побочных эффектах: thread это как бы другая программа, независимая от главной, в смысле очередности обработки данных, событий и вызова функций.
В Helpe есть описание метода Synchronize. Но лично я использовал другой метод: посылка сообщений — он более гибкий:

В файле “Form1.h”
#define Msend1 WM_USER + 1
#define Msend2 WM_USER + 2
и т.д.

class TForm1:public Tform
{ __published: ……………
public:

void __fastcall ThUpdate (TMessage &);

BEGIN_MESSAGE_MAP
MESSAGE_HANDLER ( Msend1 , TMessage , ThUpdate )
MESSAGE_HANDLER ( Msend2 , TMessage , ThUpdate )
/*и т.д. все другие сообщения для всех случаев*/
END_MESSAGE_MAP(TComponent)
}

В файле “Form1.cpp”
void __fastcall ThUpdate (TMessage &msg)
{ if ( msg.Msg == Msend1 )
{ /* здесь можно обращаться к компонентам */
Label1->Caption = “Get message from Thread”;
}
if ( msg.Msg == Msend2 )
Memo1->Lines->Add( “Получено сообщение из thread”);

/* …. и далее остальные сообщения …Можно передавать дополнительные данные в msg.WParam и msg.LParam */
};
В самом thread достаточно написать:
SendMessage ( Form1->Handle , Msend1 , 0 , 0 ) ; /*вместо 0 можно доп. параметры*/

4. Удаление. Тоже уникальный процесс. Единственная возможность — завершение функции Execute() !!! Необходимо как то сообщить этой функции, что бы она завершилась. Можно установить методом thread->Terminate() приватный член Terminated в true и периодически, в цикле проверять его значение. Если он таки true, тогда return или переход на метку exit: (см. выше) и выход. Никакими другими способами не удаляй thread !!! Естественно, если объект остановлен (Suspended==true), то сперва его следует запустить, что бы он разнюхал что к чему (см. выше). Сразу после этого вызывается функция threadend() (если только она объявлена в событии thread->OnTerminate) и в ней уже можно написать thread=NULL.

Это примитивный пример, как из объекта написать строчки в Label1 и Memo1.
Выглядит это не очень радостно, но такова плата за многопоточность…


Steam-x
  Отправлено: 18.06.2004, 11:13


Дежурный стрелочник

Группа: Участник
Сообщений: 60



Привет! И спасибо за проявленное внимание к моему вопросу!
Многопоточность есть!!!
Ура! Товарищи! Это победа человеческого разума над бездушным механизмом!
Но, маленькие програмки — маленькие сложности, и соответственно — большие программищи — гиганская куча проблем!!!

- Как отлаживать поток?
Я не могу тормозить на брекпоинтах и др. — так чего же делать?
Как проверить что происходит в потоке?
Георгий
Отправлено: 18.06.2004, 22:12


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



отладочная печать в файл — открываешь файл через fstream и спокойно пишешь в него
Guest
Отправлено: 19.06.2004, 16:24


Не зарегистрирован







>> — Как отлаживать поток?
>> Я не могу тормозить на брекпоинтах и др. — так чего же делать?
>> Как проверить что происходит в потоке?

В смысле отладки поток ничем не отличается от остальной программы.
Тормози если надо на брекпойнтах — а в чем проблема?
Steam-x
Отправлено: 21.06.2004, 09:56


Дежурный стрелочник

Группа: Участник
Сообщений: 60



Да проблем особенно нет, но некоторые вещи ведут себя странно?!
Ну, ладно с этим я как-то справлюсь, а не справлюсь — что-нибудь придумаю...
Все!
Успехов!

Вернуться в Вопросы программирования в C++Builder