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

 
потоки и формы
** Tatiana
Отправлено: 04.10.2005, 06:21


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







В программе две формы. В одной при нажатии кнопки пвтаюсь вызвать поток, использующий vcl, но при его выполнении зависает вся программа. Как сделать, чтобы этого не происходило?


CODE
void __fastcall TForm3::Button1Click(TObject *Sender)
{
 TForm1 *F=new TForm1(Application);
 F->Show();
}


//------------------------------------------------------------------------
void __fastcall TTr::Execute()
{
       Synchronize(Exec);
}
//---------------------------------------------------------------------------
void __fastcall TTr::Exec()
{
       form->upd();
}
//---------------------------------------------------------------------------

void  TForm1::upd()
{
 while(1)
   Label1->Caption=Edit1->Text;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 TTr *t=new TTr(false);
 t->FreeOnTerminate=true;
 t->form=this;
}
//------------------------------------------------------------------




Отредактировано Gedeon — 04/10/2005, 07:43
Gedeon
Отправлено: 04.10.2005, 07:46


Ветеран

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



Ну и чему Вы удивляетесь
QUOTE

while(1)

всегда истинно, поэтому и происходит постоянная
QUOTE

Label1->Caption=Edit1->Text;

Вот поток постоянно и занят
GIZMO
Отправлено: 04.10.2005, 09:43


Машинист паровоза

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



QUOTE (Gedeon @ 04/10/2005, 07:46)
Ну и чему Вы удивляетесь
QUOTE

while(1)

всегда истинно, поэтому и происходит постоянная
QUOTE

Label1->Caption=Edit1->Text;

Вот поток постоянно и занят

Ну и что? Занят то вторичный поток, а висит программа (т.е. mainthread).
while(1) — это нормально в потоке...
Почему не работает?
- Не надо ставить цикл в TForm1::upd(). Почему надеюсь объяснять не надо.
CODE

//---------------------------------------------------------------------------
class TForm1;
class MyThread : public TThread
{
private:
   TLabel *pLabel;
protected:
   void __fastcall Execute(void);
   void __fastcall UpdateLabel(void);
public:
   __fastcall MyThread(bool CreateSuspended, TLabel *ALabel);
};
//---------------------------------------------------------------------------

__fastcall MyThread::MyThread(bool CreateSuspended, TLabel *ALabel)
   : TThread(CreateSuspended), pLabel(ALabel)
{
   FreeOnTerminate = true;
}
//---------------------------------------------------------------------------
void __fastcall MyThread::Execute()
{
   //---- Place thread code here ----
   while(!Terminated/*1*/) //while(1)так тоже работает, но выйти нам как-то надо?
       Synchronize(UpdateLabel);

}
//---------------------------------------------------------------------------
void __fastcall MyThread::UpdateLabel()
{
   //TODO: Add your source code here
   static int i;
   if(pLabel)
       pLabel->Caption = IntToStr(i++);
}
//use
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   mtd = new MyThread( false, Label1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   mtd->Terminate();
}
//---------------------------------------------------------------------------


Gedeon
Отправлено: 04.10.2005, 09:54


Ветеран

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



Ну вообще говоря да. Я неправильно написал то, что имел ввиду, а по поводу
QUOTE

while(1) — это нормально в потоке...

ИМХО не нормально нигде, т.к. если уж нужен бесконечный цикл, то лучше
CODE

for(;;)

читаемость кода упрощается.
** Tatiana
Отправлено: 04.10.2005, 10:14


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







Да я нарочно этот бесконечный цикл поставила для теста потока biggrin.gif
** Tatiana
Отправлено: 04.10.2005, 10:26


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







На самом деле в цикле будет добавление точек в Series TChart-а, но т.к. точек очень много, а тормозить прогу не хочется, решила сделать поток. Значения будут браться из ADOQuery на той же форме. Как это лучше организовать?
Gedeon
Отправлено: 04.10.2005, 11:03


Ветеран

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



Ну я надеюсь Вы поняли смысл разговора, добавлять точки надо не мотодом формы, а непосредственно работая с чартом из функции в потоке.
olegenty
Отправлено: 04.10.2005, 11:20


Ветеран

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



я бы на PostMessage всё это сделал...
Konstantine
Отправлено: 04.10.2005, 14:05


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

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



а насколько долго?
весь прикол как раз в том — что Вы работаете с компонентой через Synchronize — т.е. опять-таки через основной поток...
прямо из дополнительного потока работать с компонентами тоже нельзя — в лучшем случае будет очень долго обрабатываться, в худшем — вываливаться...
сделать лучше всего так (как предложил olegenty):
for
{//тело Вашего цикла
...
Application->ProcessMessages(); // вот это и будет делать обработку сообщений, в т.ч. и прорисовку окна и обработку кнопок
}
Gedeon
Отправлено: 04.10.2005, 15:24


Ветеран

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



имеется ввиду напрямую с компонентом через synchronize а не напрямик из потока, если через метод формы то Application->ProcessMessages(); поможет, но я бы так не делал. olegenty предлагает сделать несколько иначе т.е. из потока PostMessage, а в форме эти сообщения ловить и рисовать, но я бы тоже пожалуй не стал возиться с мэссэджами ради этого.
olegenty
Отправлено: 04.10.2005, 16:36


Ветеран

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



ну это смотря как задача стоит. если мессаг мало — почему бы и нет. если много — можно сделать и мало, наладив "фильтрацию" "радиосигнала". например — мессага всего одна: CM_MOTHERFUCKING_MESSAGE, LParam — флаг, определяющий, что являет собой WParam, WParam — инфа. и какие тогда проблемы? работай — нехочу...
Konstantine
Отправлено: 05.10.2005, 11:37


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

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



не, я так и не понял — зачем поток? сделать в осн. программе, а чтоб не "висла" — в цикл включить PostMessages...
поток нужно использовать только там, где без него вообще нельзя
GIZMO
Отправлено: 06.10.2005, 08:16


Машинист паровоза

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



QUOTE (Konstantine @ 05/10/2005, 11:37)
не, я так и не понял — зачем поток? сделать в осн. программе,


... точек очень много, а тормозить прогу не хочется...
(С) Татьяна

QUOTE
а чтоб не "висла" — в цикл включить PostMessages...

И как это будет выглядеть, можно взглянуть?
Konstantine
Отправлено: 06.10.2005, 09:00


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

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



ohmy.gif оговорился — не PostMessages а ProcessMessages
если правильно расставить ProcessMessages, то торможения не будет (хоть и проц на 100% будет пахать)

пример я уже показывал — повторюсь:
CODE
while(куча раз) // или for
{Application->ProcessMessages();
... Ваши вычисления и построение точки
}
выполнение Application->ProcessMessages(); — это обработка входящих сообщений форме — прорисовка, обработка клавишь и мыши... т.е. в этом месте цикл приостанавливается, чтоб обработать "зависание". после обработки проц возвращается и продолжает цикл...

простейший пример:
на форме Button1 — для запуска цикла и CheckBox1 — для остановки...
CODE
void __fastcall TForm1::Button1Click(TObject *)
{
while(!CheckBox1->Checked)
{Application->ProcessMessages();
}
}


Отредактировано Konstantine — 06/10/2005, 10:38

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