Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Завершение потока


Автор: Bima 7.12.2006, 08:00
Взял пример для реализации потока. Я переделал его под 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 кнопкой я пытаюсь их все остановить.
Как мне сделать, что бы это все выполнялось правильно???

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

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

Автор: dumb 7.12.2006, 08:59
Цитата(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); // иначе съест все
      }
   }
}
//---------------------------------------------------------------------------

Автор: Bima 7.12.2006, 09:23
вот переделанный код:
Код

//---------------------------------------------------------------------------
#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

Автор: dumb 7.12.2006, 09:46
Код

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


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

Автор: Bima 7.12.2006, 09:56
Цитата

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) выскакивает ошибка!

Автор: GL_basik 7.12.2006, 10:34
Terminate будет работать если установить в процедуре execute пердусмотреть выход по свойтву Terminated. Например
Код

if (Terminated) return (errorcode);

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

Автор: Bima 7.12.2006, 10:48
Цитата

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

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

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

Цитата

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

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

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

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

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

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

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

Судя по приведенному коду, после инициализации она уходит в цикл с параметром и естественно проверки условия завершния не происходит. Пока не завершится этот цикл.

Автор: Bima 7.12.2006, 11:24
что разве в этом коде нет проверки условия?
Код

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


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

Автор: dumb 7.12.2006, 11:47
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);
  }
}

Автор: Bima 7.12.2006, 14:13
Цитата

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, но все равно сомневаюсь, освободится ли память после потоков или нет?

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

Память после потоков освободится. Я проверял. Это нормальное завершение потока. При выходе из процедуры Execute, объект уничтожается.

Автор: Bima 7.12.2006, 15:47
все, тема закрыта, всем спасибо.

Автор: dumb 7.12.2006, 15:47
Цитата(Bima @  7.12.2006,  14:13 Найти цитируемый пост)
Виноват, прогнал

ну, это не ты прогнал, а я.

Цитата(Bima @  7.12.2006,  14:13 Найти цитируемый пост)
я при закрытии формы убиваю потоки так:

если ты закрываешь главную форму(т.е. приложение после этого завершается), то можешь, в принципе, вообще не беспокоиться о потоках - система грохнет все, что было порождено твоим процессом.
но по правилам хорошего тона - завершать нужно. и мало того - еще и подождать в основном потоке завершения остальных. smile

чет ты опять наворотил...
Код

while (!Terminated)
   {
   FlagQuit = true; // ??
   do {
      Sleep(100);
      } while (FlagQuit);
   for(i=0;i<5000 && !FlagQuit; i++)
      {
      Application->ProcessMessages(); // это тут зачем?
      Synchronize(ShowParam);
      }
   }

зачем ты тут флаг в цикле выставляешь, если он является механизмом внешнего воздействия на поток?

Автор: Bima 7.12.2006, 15:58
Ну вот, только пометил, что вопрос решенный smile

Цитата

зачем ты тут флаг в цикле выставляешь, если он является механизмом внешнего воздействия на поток?


Здесь я ставлю флаг, что бы после выполнения цикла (for) и при первом заходе сюда программа останавливалась на цикле (do... while).

Вот и у меня получается, что при создании формы потоки создаются и крутятся на цикле (do... while) и ждут, когда флаг FlagQuit  будет false.  После этого выполняется цикл (for) и если во время выполнения, флаг FlagQuit будет принудительно сброшен в true то он снова перейдет на цикл (do... while) и все пойдет сначала. Если цикл (for) дойдет до своего конца, то что бы снова уйти в паузу, как раз и нужна эта команда FlagQuit = true.

если есть более рациональное решение, то прошу пример в студию smile.

Автор: dumb 7.12.2006, 16:12
Цитата(Bima @  7.12.2006,  15:58 Найти цитируемый пост)
Если цикл (for) дойдет до своего конца, то что бы снова уйти в паузу

а... ну да.. забыл этот момент из описания задачи. а ProcessMessages то зачем? - не место ему тут.

Автор: Vyacheslav 7.12.2006, 16:33
Цитата(dumb @  7.12.2006,  15:47 Найти цитируемый пост)
если ты закрываешь главную форму(т.е. приложение после этого завершается), то можешь, в принципе, вообще не беспокоиться о потоках - система грохнет все, что было порождено твоим процессом.

Угуsmile. Правда при закрытии программы, и наличии работающих потоков может выкинутся  Exception, но то что все освободится - это точно. Все таки Win32 smile
Вообще - то

Цитата(Bima @  7.12.2006,  15:47 Найти цитируемый пост)
я при закрытии формы убиваю потоки так:

Я бы не стал так делать. Terminate не завершает насильно нитку подобно TerminateThread, а лишь устанавливает Terminated в true. Так что, вызов Terminate() не гарантирует, что поток завершится. Задержка может быть вызвана либо ошибкой программиста( не удосужился в Execute установить проверку флага  Terminated ), либо потому, что время между проверками относительно длительное. 
Последнее не очень страшно, если приложение должно продолжить работу после завершения нитки и тогда FreeOnTerminate к месту, но ... если приложенин должно тут же завершиться, то могут (не  обязательно, но всетаки возможно) возникнуть проблемы. Я бы на твоем месте поступил бы следующим образом . Установил бы FreeOnTerminate=false
и уничтожал бы так
Код

__fastcall TForm1::~TForm1()
{
   for(int i=0;i<3;i++)
   {
      m_Download[i]->Terminate();
      m_Download[i]->WaitFor();  //ждем пока не завершится Execute
      delete    m_Download[i];
   }
}



И еще одно. Почему  не используешь внутрение средства для временной отстановки нитки
Ведь вот это все  
Код

  FlagQuit = true;
   do {
      Sleep(100);
      } while (FlagQuit);

и этого
Код

void __fastcall TForm1::Button1Click(TObject *Sender)
{
MDownload[0]->FlagExit(false);
}

просто можно заменить одно строчкой
Код

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  MDownload[0]->Suspend();
}

и нитка замрет

Правда в код по уничтожению ниток придется ввести еще проверку
Код

   for(int i=0;i<3;i++)
   {
      if (  m_Download[i]->Suspended) {
           m_Download[i]->Resume()
      }
     m_Download[i]->Terminate();
     m_Download[i]->WaitFor();  //ждем пока не завершится Execute
     delete    m_Download[i];
   }



Автор: Bima 8.12.2006, 07:16
Цитата

просто можно заменить одно строчкой

 void __fastcall TForm1::Button1Click(TObject *Sender)
{
  MDownload[0]->Suspend();
}


я сначала пробовал этот метод, но загвостка в том, что он ПРИОСТАНАВЛИВАЕТ поток, а потом командой m_Download[0]->Resume() его продолжает с того места откуда он остановился. А мне нужно что бы поток сбросился (но не убился) и потом его снова возобновить С НАЧАЛА.

Я уже подумываю, что может лучше будет каждый раз убивать потоки и потом их снова создавать, а то  инструкция:
Код

  FlagQuit = true;
   do {
      Sleep(100);
      } while (FlagQuit);

меня сильно настораживает. Вроде как бы программа в это время не должна работать, а она постоянно отрабатыват циклы задержки (sleep) с проверкой на флаг.

Что лучше в этом случае, постоянно создавать и убивать потоки или использовать цикл задержки (sleep) ???

Цитата

Правда в код по уничтожению ниток придется ввести еще проверку

    for(int i=0;i<3;i++)
   {
      if (  m_Download[i]->Suspended) {
           m_Download[i]->Resume()
      }
     m_Download[i]->Terminate();
     m_Download[i]->WaitFor();  //ждем пока не завершится Execute
     delete    m_Download[i];


 
Vyacheslav  проясни еще один момент. А если поток ушел в длительную обработку информации (не как у меня в примере), допустим команда в потоке ждет информацию от устройства, а устройство умерло. Что в этом случае произойдет, при уничтожении потока, программа будет ждать пока завершиться Execute??? Я вот про это место пишу:
Код

m_Download[i]->WaitFor();  //ждем пока не завершится Execute


Я правильно помнимаю, что в этом случае, поток вообще не завершиться или нет???

Автор: Vyacheslav 8.12.2006, 11:18
Цитата(Bima @  8.12.2006,  07:16 Найти цитируемый пост)
Я правильно помнимаю, что в этом случае, поток вообще не завершиться или нет???

Совершенно верно.
Цитата

Unlike the Windows API TerminateThread, which forces the thread to terminate immediately, the Terminate method merely requests that the thread terminate. 

Что бы насильно завершить поток нужно использовать АPI-шную функцию. Если это тебе нужно то
в твоем MyThred напиши еще один метод
Примерно так
Код

bool __fastcall MyThread::TerminateThread( int exitCode)
{
    return TerminateThread( Handle, exitCode);
);

Этот точно должен грохнуть нитку




Автор: Bima 8.12.2006, 13:02
Vyacheslav
а как Handle потока получить? и что передавать в exitCode???

на реальном примере как это написать???

Автор: Vyacheslav 8.12.2006, 13:32
Цитата(Bima @  8.12.2006,  13:02 Найти цитируемый пост)
 как Handle потока получить

Его не надо получать smile Он просто есть. 

Цитата

Contains the thread's handle.

__property int Handle = {read=FHandle, nodefault};

Description

Use Handle when calling Win32 API functions for thread manipulation.



exitCode - просто код возврата, что бы потом можно проанализировать с каким кодом завершился тред 
Если код не интересут, то
Код

bool __fastcall MyThread::TerminateThread( )
{
    return TerminateThread( Handle, 0);
);




Автор: Bima 8.12.2006, 14:19
У меня ошибку при компиляции выдает:
[C++ Error] kod.cpp(73): E2227 Extra parameter in call to _fastcall MyTread::TerminateThread()

Вроде везде все правильно объявил функцию....
даже вначале прописал:
#include "winbase.h"

почему не выходит не пойму smile

Автор: Vyacheslav 8.12.2006, 14:41
Код

bool __fastcall MyThread::TerminateThread( )
{
    return ::TerminateThread( Handle, 0);
);



Автор: Bima 8.12.2006, 14:59
не выходит smile
ругается на ноль в конце:
[C++ Error] kod.cpp(73): E2034 Cannot convert 'const unsigned int' to 'void *'

Автор: Vyacheslav 8.12.2006, 15:45
Код

 bool __fastcall MyThread::TerminateThread( )
{
    Suspend();
    return ::TerminateThread( (void*)Handle, 0);
}


Автор: Bima 11.12.2006, 06:45
Все заработало. Vyacheslav, спасибо за подсказки и за реализацию кода.
Vyacheslav скажи, а зачем в последнем топике нужно было приостанавливать поток???
Код

 bool __fastcall MyThread::TerminateThread( )
{
    Suspend(); // зачем эта строчка???????
    return ::TerminateThread( (void*)Handle, 0);
}


Как я понимаю, здесь нужно именно убить поток, а если он не приостановится???? так и будет висеть в команде Suspend???

Автор: Vyacheslav 11.12.2006, 11:01
Приостановится он всегда. А приостановить его стоит для того, что бы не словить исключение при его уничтожении из-за того, что в момент уничтожения он продолжает крутится. Хотя вполне возможно TerminateThread сама предварительно  перед уничтожением приостанавлиавент егою

Автор: Bima 11.12.2006, 11:18
всем спасибо. тема закрыта

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)