Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Завершение потока, Правильное завершение потока 
V
    Опции темы
Bima
Дата 7.12.2006, 08:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Взял пример для реализации потока. Я переделал его под 3 потока, но не могу остановить потоки, когда они запущены.

вот пример:
Код

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "kod.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
MyTread *MDownload[3];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i=0;i<3;i++)
   {
   MDownload[i]= new MyTread(true);
   MDownload[i]->Parametr(i+1);
   MDownload[i]->FlagExit(true);
   MDownload[i]->Resume();
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
MDownload[0]->FlagExit(true);
MDownload[1]->FlagExit(true);
MDownload[2]->FlagExit(true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MDownload[0]->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
MDownload[1]->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
MDownload[2]->Resume();
}
//---------------------------------------------------------------------------




//   Описание класса потока  
__fastcall MyTread::MyTread(bool CreateSuspended):TThread(CreateSuspended){}
//---------------------------------------------------------------------------
void __fastcall MyTread::Parametr(int Par)
{
GlobParam=Par;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::FlagExit(bool Flag)
{
FlagQuit=Flag;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::Execute()
{
FreeOnTerminate=true;
while (FlagQuit)
   {
   Suspend();
   for(i=0;i<10000;i++)
      {
      Synchronize(ShowParam);
      }
   }
}
//---------------------------------------------------------------------------
void __fastcall MyTread::ShowParam()
{
switch(GlobParam)
   {
   case 1:
      Form1->Label1->Caption=IntToStr(i);
      Form1->Label1->Refresh();
      break;
   case 2:
      Form1->Label2->Caption=IntToStr(i);
      Form1->Label2->Refresh();
      break;
   case 3:
      Form1->Label3->Caption=IntToStr(i);
      Form1->Label3->Refresh();
      break;
   }
}
//---------------------------------------------------------------------------


Заголовочный файл:
Код

//---------------------------------------------------------------------------

#ifndef kodH
#define kodH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
   TButton *Button1;
   TButton *Button2;
   TButton *Button3;
   TLabel *Label1;
   TLabel *Label2;
   TLabel *Label3;
   TButton *Button4;
   void __fastcall FormCreate(TObject *Sender);
   void __fastcall Button4Click(TObject *Sender);
   void __fastcall Button1Click(TObject *Sender);
   void __fastcall Button2Click(TObject *Sender);
   void __fastcall Button3Click(TObject *Sender);
private:    // User declarations
public:        // User declarations
   __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------


//  Описание класса потока     
//---------------------------------------------------------------------------
class MyTread : public TThread
{
private:
protected:
   void __fastcall Execute();
   void __fastcall ShowParam();
   int GlobParam,i;
   bool FlagQuit;
public:
   __fastcall MyTread(bool CreateSuspended);
   void __fastcall Parametr(int Par);
   void __fastcall FlagExit(bool Flag);
};
//---------------------------------------------------------------------------

#endif


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



--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
takedo
Дата 7.12.2006, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Слушай, я в билдере не очень силен, но ты почитай темы сперва про потоки в разделе API, там очень много про это. А что касательно твоего кода, то вообще то ты знаешь, что обозначает флаг MDownload[0]->FlagExit(true);? Ты ведь для каждого потока его вызываешь при создании формы, а затем я так понял и по кнопке 4. То есть ты его сперва останавливаешь, а потом ещё раз? Может ты знаешь про потоки больше меня, может нет, но все таки ты должен знать, что поток - это отдельня фукнция, в которой ты и работаешь, когда ты говоришь о выходе из потока, ты просто выходишь из этой функции, обратного захода без порождения нового потока нету. Вообще-то дождись конечно билдеристов,  но пока тебе не помогли, почитай раздел форума по API и используй прямо от туда все API - билдер ведь их поддерживает по умолчанию, а уже потом начинай со временем применять билдеровские классы. мне кажется, так будет проще. Да, кстати, хорошо описано в Мешков, Тихомиров книга про MFC, не раз в форуме упоминалась, точное название не помню(давно уже ничего толком не программировал, книга эта настольная была всегда)
удачи smile 


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Bima
Дата 7.12.2006, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Вначале я вызываю эту функцию MDownload[i]->FlagExit(true) для того, что бы поток не запустился сразу и инициализирую переменную FlagQuit для каждого потока.
А потом запускаю поток командой MDownload[i]->Resume(); 
Причем, если я нажимаю несколько раз на первую кнопку, то столько раз запускается первый поток.
но пока поток работает, я остановить его не могу smile

Это сообщение отредактировал(а) Bima - 7.12.2006, 08:42


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
dumb
Дата 7.12.2006, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Цитата(Bima @  7.12.2006,  08:41 Найти цитируемый пост)
вызываю эту функцию MDownload[i]->FlagExit(true) для того, что бы поток не запустился сразу

достаточно того, что ты создаешь с флагом CreateSuspended.

так чуть правильней:
Код

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i=0;i<3;i++)
   {
   MDownload[i]= new MyTread(true);
   MDownload[i]->Parametr(i+1);
   }
}
//---------------------------------------------------------------------------
...
//---------------------------------------------------------------------------
//   Описание класса потока  
__fastcall MyTread::MyTread(bool CreateSuspended):TThread(CreateSuspended)
{
GlobParam = 0;
FlagQuit = false;
}
//---------------------------------------------------------------------------
...
//---------------------------------------------------------------------------
void __fastcall MyTread::Execute()
{
FreeOnTerminate=true;
while (!Terminated && !FlagQuit)
   {
   for(i=0;i<10000;i++)
      {
      Synchronize(ShowParam);
      Sleep(500); // иначе съест все
      }
   }
}
//---------------------------------------------------------------------------

PM MAIL   Вверх
Bima
Дата 7.12.2006, 09:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



вот переделанный код:
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "kod.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
MyTread *MDownload[3];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i=0;i<3;i++)
   {
   MDownload[i]= new MyTread(true);
   MDownload[i]->Parametr(i+1);
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
MDownload[0]->FlagExit(true);
MDownload[1]->FlagExit(true);
MDownload[2]->FlagExit(true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MDownload[0]->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
MDownload[1]->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
MDownload[2]->Resume();
}
//---------------------------------------------------------------------------




//   Описание класса потока  
__fastcall MyTread::MyTread(bool CreateSuspended):TThread(CreateSuspended)
{
//GlobParam = 0; при созданнии класса я думаю это лишнее, так как при создании формы я явно присваиваю этой переменной значение.
FlagQuit = false;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::Parametr(int Par)
{
GlobParam=Par;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::FlagExit(bool Flag)
{
FlagQuit=Flag;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::Execute()
{
FreeOnTerminate=true;
while (!Terminated && !FlagQuit)
   {
   for(i=0;i<10000;i++)
      {
      Synchronize(ShowParam);
      Sleep(100); //   иначе съест все
      }
   }
}
//---------------------------------------------------------------------------
void __fastcall MyTread::ShowParam()
{
switch(GlobParam)
   {
   case 1:
      Form1->Label1->Caption=IntToStr(i);
      Form1->Label1->Refresh();
      break;
   case 2:
      Form1->Label2->Caption=IntToStr(i);
      Form1->Label2->Refresh();
      break;
   case 3:
      Form1->Label3->Caption=IntToStr(i);
      Form1->Label3->Refresh();
      break;
   }
}
//---------------------------------------------------------------------------


потоки работают нормально, претензий нет, но при нажатии на кнопку 4 (процедура Button4Click), я не могу остановить потоки... счетчики работают smile


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
dumb
Дата 7.12.2006, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Код

for(i=0;i<10000, !FlagQuit, !Terminated;i++)


кстати, а чем тебе не угодило свойство Terminated из TThread? - его вполне достаточно. зачем тебе FlagQuit твой?
PM MAIL   Вверх
Bima
Дата 7.12.2006, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

for(i=0;i<10000, !FlagQuit, !Terminated;i++)

Этот код тоже не работает!!!

Цитата

кстати, а чем тебе не угодило свойство Terminated из TThread? - его вполне достаточно. зачем тебе FlagQuit твой? 


если я пишу в коде на 4 кнопке следущее:
Код

MDownload[0]->FlagExit(true);
MDownload[1]->FlagExit(true);
MDownload[2]->Terminate();

то после нажатия на нее (все потоки предварительно запустил), происходит останавливание 3 потока, но при повторном запуске его (нажать на кнопку 3) выскакивает ошибка!



--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
GL_basik
Дата 7.12.2006, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 5.9.2006

Репутация: нет
Всего: нет



Terminate будет работать если установить в процедуре execute пердусмотреть выход по свойтву Terminated. Например
Код

if (Terminated) return (errorcode);

Поток завершается только тогда, когда прекращается выполнение Execute.
Кроме того есть жесткое завршние потока с помощью API функции TerminateThread. 
Что касается ошибки. То уствнови свойство FreeOnTerminate=false. Иначе для повторного запуска поток нужно завново инициальзировать. Только не забудь очистить память, после завершния прораммы.

Это сообщение отредактировал(а) GL_basik - 7.12.2006, 10:54
PM MAIL   Вверх
Bima
Дата 7.12.2006, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Стрнно почему не работает Terminate... А свойство Terminated устанавливается? Тогда попробуйте переписать код по другому... Вместо цикла с параметром воспользуйтесь циклом "до"...
Кроме того есть жесткое завршние потока с помощью API функции   TerminateThread. 

Переписывание цикла "до".... ничего не даст, так как программа туда заходит только один раз при инициализации, потом она туда не заходит. Ставил там breakPoint и проверял. почему это происходит не знаю smile

Terminate завершает поток, отсюда и ошибка выскакивает, так как я пытаюсь использовать поток, который завершился.

Цитата

Что касается ошибки. То уствнови свойство FreeOnTerminate=false. Иначе для повторного запуска поток нужно завново инициальзировать. Только не забудь в конце очистить память.

пытался я так делать, но в этом случае поток все равно завершается, и не запускается, хотя в этом случае ошибку не выдает. Хотя так и должно быть, так как поток завершен, в памяти он остался, но не запущен.

пока задача не решена smile

Добавлено @ 10:58 
Что бы было понятнее, я напишу, что я хочу сделать.

Есть программа в которой есть несколько задач. Эти задачи могут выполнятся длительное время и они должны выполнятся параллельно. По истечении определенного времени(TimeOut), если задача не выполнена, задача должна быть завершена (Это реализуется легко, если знать, как корректно завершить задачу).  Есть еще одно условие в програме - задачи должны через определенное время перезапускаться.

Из всего написаного я сделал вывод, что нужно использовать потоки, которые будут запускаться по таймеру. Постоянно создовать потоки нет смысла и выгружать их из памяти тоже, поэтому я решил, что лучше создать все потоки при создании программы и убить их все во время завершения программы. Для эмуляции задачи написал простой счетчик (см. код программы), который хочу остановить по нажатию кнопки. Дальше при реализации завершения потока быду вставлять таймеры и двигаться от простого к сложному. Вот вроде и вся реализация, которою я надумал.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
GL_basik
Дата 7.12.2006, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 5.9.2006

Репутация: нет
Всего: нет



Цитата(Bima @ 7.12.2006,  10:48)
Переписывание цикла "до".... ничего не даст, так как программа туда заходит только один раз при инициализации, потом она туда не заходит. Ставил там breakPoint и проверял. почему это происходит не знаю smile

Судя по приведенному коду, после инициализации она уходит в цикл с параметром и естественно проверки условия завершния не происходит. Пока не завершится этот цикл.
PM MAIL   Вверх
Bima
Дата 7.12.2006, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



что разве в этом коде нет проверки условия?
Код

   for(i=0;i<10000, !FlagQuit, !Terminated;i++)
      {
      Synchronize(ShowParam);
      Sleep(100); //   иначе съест все
      }


я думал, что после выполнения коменд внутри цикла (Synchronize и Sleep) управление передается на проверку условия (достигло ли i значения 1000 и нет ли флагов FlagQuit, Terminated)
или я не прав???


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
dumb
Дата 7.12.2006, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Bima,
фор надо было так сделать:
Код

for(i=0;i<10000 && !FlagQuit && !Terminated;i++)


а если тебе нужно притормаживать потоки с возможностью их продолжения, то так и надо было говорить. в таком случае тебе нельзя выходить из Execute. для приостановки пользоваться либо Suspend(тут торможение происходит в любом месте цикла, что зачастую неприемлимо), либо доп.флагом.
например так:
Код

void __fastcall MyTread::Execute()
{
  FreeOnTerminate=true;
  while (!Terminated)
  {
    i++;
    Synchronize(ShowParam);
    do {
      Sleep(100);
    } while (FlagSuspend);
  }
}

PM MAIL   Вверх
Bima
Дата 7.12.2006, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Bima,
фор надо было так сделать:

 for(i=0;i<10000 && !FlagQuit && !Terminated;i++)


Виноват, прогнал  smile  smile 

dumb спасибо за подсказку. Реализовал я примерно так, как ты написал. Вроде работает так как я хотел. Вот код:
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "kod.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
MyTread *MDownload[3];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i=0;i<3;i++)
   {
   MDownload[i]= new MyTread(true);
   MDownload[i]->Parametr(i+1);
   MDownload[i]->Resume(); //  для создания потока
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
MDownload[0]->Terminate();
MDownload[1]->Terminate();
MDownload[2]->Terminate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)
{
MDownload[0]->FlagExit(true);
MDownload[1]->FlagExit(true);
MDownload[2]->FlagExit(true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MDownload[0]->FlagExit(false);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
MDownload[1]->FlagExit(false);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
MDownload[2]->FlagExit(false);
}
//---------------------------------------------------------------------------




//    описание класса потока
__fastcall MyTread::MyTread(bool CreateSuspended):TThread(CreateSuspended)
{
//FlagQuit = true; //убрал за ненадобностью
}
//---------------------------------------------------------------------------
void __fastcall MyTread::Parametr(int Par)
{
GlobParam=Par;
}
//---------------------------------------------------------------------------
void __fastcall MyTread::FlagExit(bool Flag)
{
FlagQuit=Flag;
}
//---------------------------------------------------------------------------

void __fastcall MyTread::Execute()
{
FreeOnTerminate=true;
while (!Terminated)
   {
   FlagQuit = true;
   do {
      Sleep(100);
      } while (FlagQuit);

   for(i=0;i<5000 && !FlagQuit; i++)
      {
      Application->ProcessMessages();
      Synchronize(ShowParam);
      }
   }
}
//---------------------------------------------------------------------------
void __fastcall MyTread::ShowParam()
{
switch(GlobParam)
   {
   case 1:
      Form1->Label1->Caption=IntToStr(i);
      Form1->Label1->Refresh();
      break;
   case 2:
      Form1->Label2->Caption=IntToStr(i);
      Form1->Label2->Refresh();
      break;
   case 3:
      Form1->Label3->Caption=IntToStr(i);
      Form1->Label3->Refresh();
      break;
   }
}
//---------------------------------------------------------------------------


Остался последний вопрос.
я при закрытии формы убиваю потоки так:
Код

MDownload[0]->Terminate();
MDownload[1]->Terminate();
MDownload[2]->Terminate();

Стоит ли это делать? Вроде я поставил FreeOnTerminate=true, но все равно сомневаюсь, освободится ли память после потоков или нет?


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
GL_basik
Дата 7.12.2006, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 5.9.2006

Репутация: нет
Всего: нет



Цитата(Bima @ 7.12.2006,  14:13)
Стоит ли это делать? Вроде я поставил FreeOnTerminate=true, но все равно сомневаюсь, освободится ли память после потоков или нет?

Память после потоков освободится. Я проверял. Это нормальное завершение потока. При выходе из процедуры Execute, объект уничтожается.
PM MAIL   Вверх
Bima
Дата 7.12.2006, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



все, тема закрыта, всем спасибо.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0587 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.