Green |
Отправлено: 17.01.2005, 07:30 |
|
Не зарегистрирован
|
Нужно создать многопоточное приложение. И продемострировать синхронизацию. У кого нибудь есть что-то подобное?
Приложение создал(три потока), а вот с синхронизацией проблемы.
Вот увижу рабочий код, пойму как ее(синхронизацию) организовывать.
Помогите. |
|
Doga |
Отправлено: 17.01.2005, 12:14 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
https://rxlib.ru/forums/index.php?ac...e3eab6e29e27154
Или поиск по форуму
|
|
Георгий |
Отправлено: 17.01.2005, 13:36 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
http://www.cbuilder.ru/WinLesson/bles2.htm |
|
Тиграша |
Отправлено: 01.03.2005, 08:55 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
Чего-то я с потоками втупляю...
Есть TThread* TTh
CODE |
void __fastcall TTh::Execute()
{
this->FreeOnTerminate = true;
while(!Terminated){
if(Terminated){break;}//;-)
Synchronize(Action);
}
}
|
Вызываю Th->Terminate();
И после этого всё-таки Th!=NULL.
Оч. хочется сделать Th=NULL.
Как сделать?
Отредактировано Тиграша — 01/03/2005, 09:15 |
|
Gedeon |
Отправлено: 01.03.2005, 09:21 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
CODE |
Th->OnTerminate = ThTerminate; // Ваша ф-ция обработчик в юните вызова нити
void __fastcall TForm1::ThTerminate(TObject *Sender)
{
Th=NULL;
}
//--------------------------------------------------------------------------- |
|
|
Konstantine |
Отправлено: 01.03.2005, 09:24 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
ну не равен... а указатель можно и нулём сделать пока процесс работает... ему ничё не будет — просо доступа к нему не будет и делов-то... поэтому сделали Terminate и не дожидаясь можно обнулить — если уверены, что процесс завершиться нормально
|
|
Тиграша |
Отправлено: 01.03.2005, 09:32 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
2Konstantine — Мне же именно хочется в вызывающем приложении дождаться нормального завершения части потоков.
А как я узнаю, что объекты delete корректно?
2Gedeon — Th=NULL; Странно... Мне кажется такое — не в русле идеологии TThread Они вроде бы для того и сделали Terminate...
Отредактировано Тиграша — 01/03/2005, 09:42 |
|
Gedeon |
Отправлено: 01.03.2005, 09:51 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (Тиграша @ 01/03/2005, 07:32) | Мне же именно хочется в вызывающем приложении дождаться нормального завершения части потоков.
|
Для этого и есть событие OnTerminate.
QUOTE |
А как я узнаю, что объекты delete корректно? |
Как напишите код, так они и delete, еще отладчик помогает.
QUOTE |
2Gedeon — Th=NULL; Странно... Мне кажется такое — не в русле идеологии TThread Они вроде бы для того и сделали Terminate... |
Что не в русле? Присвоение указателю значения NULL? .
Terminate сделан для того, чтобы установить флаг завершения потока, к-рый между прочим Вы должны отслеживать и поток завершать.
|
|
Bond |
Отправлено: 01.03.2005, 10:38 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Вообще-то не политкоректно рабочему указателю присваивать значение NULL.
Даже если мы уверены что он не используется, тогда зачем?
|
|
Guest |
Отправлено: 01.03.2005, 10:59 |
|
Не зарегистрирован
|
QUOTE | Вообще-то не политкоректно рабочему указателю присваивать значение NULL.
|
А в таком аспекте:
CODE |
if (!FSubForm) TFSubForm = new TFSubForm(Application);
try {
FSubForm->Visible = false;
...
FSubForm->ShowModal();
...
}
catch (Exception &xcp) { ShowMessage(xcp.Message); }
delete FSubForm;
FSubForm = NULL;
| |
|
Bond |
Отправлено: 01.03.2005, 11:11 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
QUOTE | Th->OnTerminate = ThTerminate; // Ваша ф-ция обработчик в юните (1) вызова нити
void __fastcall TForm1::ThTerminate(TObject *Sender)
{
Th=NULL; // (2)
} |
(2) — обнуливается указатель в функции, которая была вызвана по этому указателю (1)
а тутQUOTE | delete FSubForm;
FSubForm = NULL; | указатель обнуливается сразу после явного освобождения памяти.
Это даже необходимо делать для возможности проверить позже, была ли освобождена память из-под него — что парирует неккоректное обращение к освобожденной ранее памяти
|
|
Gedeon |
Отправлено: 01.03.2005, 11:37 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (Bond @ 01/03/2005, 08:38) | Вообще-то не политкоректно рабочему указателю присваивать значение NULL.
Даже если мы уверены что он не используется, тогда зачем? |
1) Вообщето об этом вопрошал автор топика.
2) Проверять пустой ли указатель для создания/несоздания новой нити.(зависит от логики программы).
3) Дабы не обратиться к уже уничтоженному обьекту.
QUOTE |
TThread::OnTerminate
Occurs after the thread's Execute method has returned and before the thread is destroyed. |
Да, нить еще не уничтожена, но будет по завершении данной функции, что плохого если тут присвоить указателю 0?
Как по другому Вы предлагаете это делать?
Отредактировано Gedeon — 01/03/2005, 09:40
|
|
Тиграша |
Отправлено: 01.03.2005, 11:47 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
Спрашивал я собственно о том, как корректно уничтожить TThread* Th. OnTerminate у меня есть, проверил — выполняется по Terminate(), а Th — всё равно не NULL
Отредактировано Тиграша — 01/03/2005, 11:49 |
|
Bond |
Отправлено: 01.03.2005, 11:53 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Борландовский компиллер (не знаю на счет остальных) после выполнения операции delete Ptr; не задает указателю Ptr значение NULL
|
|
Тиграша |
Отправлено: 01.03.2005, 12:08 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
И что же мне бедному делать?
Message в главный объект слать, что каждый нужный поток выполнил OnTerminate и тогда уже делать Th = NULL? |
|
Gedeon |
Отправлено: 01.03.2005, 13:14 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (Bond @ 01/03/2005, 09:53) | Борландовский компиллер (не знаю на счет остальных) после выполнения операции delete Ptr; не задает указателю Ptr значение NULL |
А какой компилятор это делает?
При чем тут вообще компилятор?
При удалении указателю нигде в ++ ноль не присваивается, кстати в дэлфи тоже.
2Тиграша
Делайте так, как я написал, что Вас не устраивает?
Отредактировано Gedeon — 01/03/2005, 11:15
|
|
Gedeon |
Отправлено: 01.03.2005, 13:19 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (Тиграша @ 01/03/2005, 09:47) | Спрашивал я собственно о том, как корректно уничтожить TThread* Th. OnTerminate у меня есть, проверил — выполняется по Terminate(), а Th — всё равно не NULL |
Если стоит FreeOnTerminate = true; поток корректно уничтожится.
Th — всё равно NULL не будет без явного присвоения. Если надо чтоб был 0 только для этой проверки — это неправильно.
Если хочется проверить все ли удаляется — CodeGuard.
|
|
Тиграша |
Отправлено: 01.03.2005, 13:29 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
Не, Gedeon, всё-таки я тебя не понял.
Смотри — из главной формы вроде бы плохо обнулять указатель — а мало ли что там с объектом происходит, а у меня пара объектов вообще без исходов, и что они там делают — я точно и не знаю.
В какой момент-то это делать?
Поторюсь — мне по сути надо корректно дождаться завершения некоторых TThread.
Если тебе не в лом — можж я для примеру один сырец выложу — посмотришь?
P.S. Я сегодня чего-то увольняться собрался, так что некогда пока, но вроде бы дело пошло — оч.хитёр один объект у меня, пытается оставить в системе "внука" Так что спасибо all за обсуждение.
Отредактировано Тиграша — 02/03/2005, 12:39 |
|
Bond |
Отправлено: 01.03.2005, 13:38 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
1. delete — кажется является служебным словом, кое обрабатывает компилятор (зачем так жестко). Я просто уточнил.
2. Если неизвестно что делают thread-ы — указатель нельзя обнуливать. Можно ввсети флаги или еще что-то и их обрабатывать в OnTerminate
|
|
Konstantine |
Отправлено: 01.03.2005, 13:55 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
дождаться можно методом WaitFor()
|
|
Gedeon |
Отправлено: 01.03.2005, 14:16 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
ну кстати это идея, по поводу присвоения 0, ну конечно если неизвестно, то нельзя, все безусловно от логики зависит.
2Тиграша
выкладывайте, от чего б не посмотреть.
|
|
Gedeon |
Отправлено: 01.03.2005, 14:54 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Вот кстати обсуждалось
Указатель на обьект. Живой или мертвый.
|
|
Тиграша_ |
Отправлено: 04.05.2005, 06:19 |
|
Не зарегистрирован
|
Всё-таки забавный зверёк этот TThread
Столкнулся:
есть TForm* MainForm, которая создаёт 2 штуки TThread с нормальными приоритетами, которые начинают общаться между собой. И MainForm по идее должна быть управляющей для этих TThread. Всё нормально до тех пор, пока потоки обмениваются данными с MainForm достаточно быстро. Но в случае массированных вычислений в потоках, когда растёт время выполнения функции из Synchronize-ов, теряю MainForm — никак не могу её сделать активной...
Есть а All соображения как побеждать? |
|
Rius |
Отправлено: 04.05.2005, 06:41 |
|
Мастер участка
Группа: Участник
Сообщений: 321
|
Никогда ничего тяжелого из Synchronize не вызывать. Все считать в потоках, для того они и созданы.
Кстати, у Thread есть свойство FreeOnTerminate
|
|
Тиграша |
Отправлено: 04.05.2005, 12:45 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 24
|
Забодал путём вставки в Synchronize Application->ProcessMessages();
А можно как-нибудь ещё бодать? |
|