Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TThread: как узнать что поток унижтожен? 
:(
    Опции темы
Alca
Дата 18.3.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



TThread: как узнать что поток уничтожен?
Метод Terminated закрытый  smile 
Код

protected:
    __property bool Terminated = {read=FTerminated, nodefault};



--------------------
PM WWW ICQ Skype Jabber   Вверх
Lazin
Дата 18.3.2009, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



с помощью Wait*** функции
PM MAIL Skype GTalk   Вверх
Anikmar
Дата 18.3.2009, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата

TThread: как узнать что поток уничтожен?
Метод Terminated закрытый   


Оберните Tthread своим классом - и получите доступ к полю
PM MAIL ICQ   Вверх
Alca
Дата 18.3.2009, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Мне надо что-то вроде этого:
Код

//...
m_pMainThread->FreeOnTerminate = true; 
//...
void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    if (false == m_pMainThread->Terminated) {
        m_pMainThread->Terminate();
    }
}


Это сообщение отредактировал(а) Alca - 18.3.2009, 17:05


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 18.3.2009, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Ну и создайте свой класс:

Код

class MyTThread : public TThread
{
public:
bool GetTerminated(void) { return Terminated; };
};

И уже проверяйте у себя так:
Код

//...
m_pMainThread->FreeOnTerminate = true; 
//...
void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    if (!m_pMainThread->GetTerminated()) {
        m_pMainThread->Terminate();
    }
}


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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



Anikmar, скорее всего из этого ничего не выйдет. Terminate() и Terminated служат для безболезненного завершения потока. Т.е. Terminate() сама по себе ничего не делает, кроме как взводит флаг Terminated. А Terminated используется в главной функции (Execute):
Код

...
TStringList *mylist;
TMemoryStream *mystream;
mylist = new TStringList();
... // бла бла
if(Terminated)
{
  mylist->Free();
  // ещё что-нибудь делаем
  return; // завершаем работу
}
mystream = TMemoryStream();
... // бла бла
if(Terminated)
{
  mylist->Free();
  mystream->Free();
  // ещё что-нибудь делаем
  return; // завершаем работу
}
// бла бла
mylist->Free();
mystream->Free();


ЗЫ покрайней мере, об этом писалось в книге...


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
mrbrooks
Дата 19.3.2009, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

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



Все это частности. Самый дельный ответ дал как всегда Lazin
Тем более у TThread есть свой метод WaitFor() - ожидающий прекращения потока.
PM MAIL   Вверх
Alca
Дата 19.3.2009, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

Тем более у TThread есть свой метод WaitFor() - ожидающий прекращения потока.

Куда его втулить? smile 

Это сообщение отредактировал(а) Alca - 19.3.2009, 10:26


--------------------
PM WWW ICQ Skype Jabber   Вверх
ksili
Дата 19.3.2009, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

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



Alca, по-моему класс TThread напрямую не используют, надо делать свой класс-наследник от TThread.
Код

MyThread->Terminate();
MyThread->WaitFor();   // ждем пока не завершится поток
.....
// работаем дальше



--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
mrbrooks
Дата 19.3.2009, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

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



Цитата(Alca @  19.3.2009,  10:24 Найти цитируемый пост)
Куда его втулить?

в хелпе к 2009 есть пример  smile 
Цитата(ksili @  19.3.2009,  10:42 Найти цитируемый пост)
Alca, по-моему класс TThread напрямую не используют, надо делать свой класс-наследник от TThread.

с этим никто не спорит.


Цитата(ksili @  19.3.2009,  10:42 Найти цитируемый пост)
Выделить всёкод C++ Builder    
MyThread->Terminate();
MyThread->WaitFor();   // ждем пока не завершится поток
.....
// работаем дальше

так делать нельзя.
PM MAIL   Вверх
Alca
Дата 19.3.2009, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Код

Alca, по-моему класс TThread напрямую не используют, надо делать свой класс-наследник от TThread.

Я так и сделал.

Добавлено через 34 секунды
Код

class CMainThread: public TThread {


Добавлено через 2 минуты и 9 секунд
Цитата

Цитата(ksili @  19.3.2009,  10:42 )
Код

MyThread->Terminate();
MyThread->WaitFor();   // ждем пока не завершится поток
.....
// работаем дальше

так делать нельзя.

Чего?


--------------------
PM WWW ICQ Skype Jabber   Вверх
Lazin
Дата 19.3.2009, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(Alca @  19.3.2009,  10:24 Найти цитируемый пост)
Куда его втулить?

я не в курсе как там это сделано в TThread
вот обычный паттерн
  • - запускаем поток
  • - ...
  • - говорим потоку что пора-бы и завершиться
  • - ждем пока завершится
Код

volatile LONG run_ = 1;

unsigned thread_fn(void*)
{
  while( InterlockedCompareExchange(&run_, 0, 0) )
  {
    ..do work.. 
  }
}


int main()
{
   DWORD threadid = 0;
   HANDLE hthread = (HANDLE)_beginthreadex(NULL, 0, &thread_fn, NULL, 0, &threadid );
   ...do work
   InterlockedExchange(&run_, 0);//сообщаем потоку о том, что нужно завершиться
   //ждем завершения потока
   DWORD wresult = WaitForSingleObject(hthread, 10000);
   if (wresult != WAIT_OBJECT_0)
   {
      std::cerr << "thread dedlocked" << std::endl;
   } 
   else
   {
      std::cout << "поток нормально остановлен" << std::endl;
   }
}

PM MAIL Skype GTalk   Вверх
mrbrooks
Дата 19.3.2009, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

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



Цитата(Alca @  19.3.2009,  10:46 Найти цитируемый пост)
Чего? 


сначало вызов Terminate():
затем WaitFor();

блин смотрите хелп!

Добавлено через 8 минут и 51 секунду
Цитата(Lazin @  19.3.2009,  10:56 Найти цитируемый пост)
я не в курсе как там это сделано в TThread

как всегда несколько проще

Код

volatile long flag;
void __fastcall Thread::Execute()
{
 while (!flag)
 {
    Synchronize(Work);
    Sleep(100);
 }
 flag = 0;
}
void __fastcall Thread::WaitStop()
{
  InterlockedIncrement(&flag);
  this->WaitFor();
}

PM MAIL   Вверх
Alca
Дата 19.3.2009, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

сначало вызов Terminate():
затем WaitFor();

А если поток уже отработал, то:
Код

System Error.  Code: 6.
Неверный дескриптор.






--------------------
PM WWW ICQ Skype Jabber   Вверх
mrbrooks
Дата 19.3.2009, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

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



Цитата(Alca @  19.3.2009,  12:34 Найти цитируемый пост)
А если поток уже отработал, то:

разумеется. я же писал - так делать нельзя. тут уже надо определиться - либо рубим поток через Terminate(), либо ждем пока он сам завершится через WaitFor() - вместе эти два метода не используются.
PM MAIL   Вверх
xvr
Дата 19.3.2009, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Alca @ 18.3.2009,  17:04)
Мне надо что-то вроде этого:
Код

//...
m_pMainThread->FreeOnTerminate = true; 
//...
void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    if (false == m_pMainThread->Terminated) {
        m_pMainThread->Terminate();
    }
}

Использование FreeOnTerminate = true несовместимо с любыми попытками узнать у объекта статус завершенности потока. Так как при завершении потока объект само уничтожится, и звать после этого от него любые методы уже нельзя - объект разрушен.


Это сообщение отредактировал(а) xvr - 19.3.2009, 13:42
PM MAIL   Вверх
Alca
Дата 19.3.2009, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

Использование FreeOnTerminate = true несовместимо с любыми попытками узнать у объекта статус завершенности потока. Так как при завершении потока объект само уничтожится, и звать после этого от него любые методы уже нельзя - объект разрушен.

а если в OnTerminate или в деструкторе потока сигналить ивентом??

Это сообщение отредактировал(а) Alca - 19.3.2009, 14:06


--------------------
PM WWW ICQ Skype Jabber   Вверх
xvr
Дата 19.3.2009, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Alca @ 19.3.2009,  14:02)
Цитата

Использование FreeOnTerminate = true несовместимо с любыми попытками узнать у объекта статус завершенности потока. Так как при завершении потока объект само уничтожится, и звать после этого от него любые методы уже нельзя - объект разрушен.

а если в OnTerminate или в деструкторе потока сигналить ивентом??

Это можно, но надо не забыть потом закрыть HANDLE этого event'а

PM MAIL   Вверх
Alca
Дата 20.3.2009, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Типа для каждого потока надо ивенты создавать?


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 20.3.2009, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата(Alca @  20.3.2009,  00:06 Найти цитируемый пост)
Типа для каждого потока надо ивенты создавать? 

Я не понимаю, чем мой подход вам не понравился? Я использовал это сто раз - все нормально, указатель обнуляется.

Конкретно доя потоков не применял, но формы у меня все самоуничтожаются и обнуляют указатели. Для потоков - аналогично все должно работать.
PM MAIL ICQ   Вверх
xvr
Дата 20.3.2009, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Alca @ 20.3.2009,  00:06)
Типа для каждого потока надо ивенты создавать?

Как то через задницу это выглядит - отпустить поток на волю (FreeOnTermiate), а потом пытаться поймать его обратно  smile Озвучите, что вы с ним хотите сделать, пока это не очень понятно

PM MAIL   Вверх
Alca
Дата 20.3.2009, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

Я использовал это сто раз - все нормально, указатель обнуляется.

Код

//...
m_pMainThread->FreeOnTerminate = true;    //true или false - пофиг
//...
assert(NULL != m_pMainThread);    //указатель не обнуляется!!!
m_pMainThread->Terminate();
//...


Добавлено @ 00:50
Цитата

Как то через задницу это выглядит - отпустить поток на волю (FreeOnTermiate), а потом пытаться поймать его обратно   Озвучите, что вы с ним хотите сделать, пока это не очень понятно

Хочу так?
Код

void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    if (false == m_pMainThread->Terminated) {
        m_pMainThread->Terminate();
    }
}

или так 
Код

void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    if (NULL != m_pMainThread) {
        m_pMainThread->Terminate();
    }
}

Короче, если поток есть, то его убить, а если он еще пашет сдох, то пропустить удаление.

Это сообщение отредактировал(а) Alca - 20.3.2009, 13:10


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 20.3.2009, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата(Alca @  20.3.2009,  00:47 Найти цитируемый пост)
Короче, если поток есть, то его убить, а если он еще пашет, то пропустить.

Я же предложил, оберните его в свой класс - и получите доступ к protected свойству - дополнительно можете спокойно изменить конструктор так, чтобы запомнить адрес указателя, и соответственно деструктор - чтобы его обнулить. 
PM MAIL ICQ   Вверх
Alca
Дата 20.3.2009, 01:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Короче сделал счетчик потоков - при запуске увеличиваю, а при OnTerminate уменьшаю.
В главной форме, при нажатии кнопки "Стоп", проверяю значение счетчика на нуль.
Если нуль, то пропускаю удаление потоков, если больше, то удаляю.  smile 
Как вам такая идейка? Может чего-то криво?

Добавлено через 1 минуту и 24 секунды
Цитата

Я же предложил, оберните его в свой класс 

Чета у меня там была какая-то лажа, надо будет еще раз проверить....


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 20.3.2009, 01:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата(Alca @  20.3.2009,  01:01 Найти цитируемый пост)
Как вам такая идейка? Может чего-то криво?

Лучше все-таки индивидуально знать состояние каждого потока. Счетчик может быть не нуль, но при удалении всех четырех кто-то модет еще жив, а кто-то нет.
PM MAIL ICQ   Вверх
Alca
Дата 20.3.2009, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

Лучше все-таки индивидуально знать состояние каждого потока.

Согласен

Добавлено через 12 минут и 5 секунд
Цитата

но при удалении всех четырех кто-то модет еще жив

В OnTerminate разве потоки не начинают разрушаться?


--------------------
PM WWW ICQ Skype Jabber   Вверх
xvr
Дата 20.3.2009, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Alca @ 20.3.2009,  00:47)
Короче, если поток есть, то его убить, а если он еще пашет, то пропустить удаление.

Вот с этого и надо было начинать  smile 
Предлагаю поменять подход - не ловить за хвост недобитые потоки, а говорить тем, кто не помер, что уже пора  smile 
В главной форме заводится event (CreateEvent) с ручным сбросом. При создании потока ему передают HANDLE этого event'а, от этого HANDLE поток делает DuplicateHandle и в дальнейшем ждет на нем (через WaitFor*Object). Когда дождался - закрывает свою копию HANDLE'а и завершается.
Главная форма, когда надо всех прибить, просто делает SetEvent & CloseHandle. Затем создает новый event для будущего использования

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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Alca,  я посмотрел ваш код - там слегка подправить пару строчек и никаких навротов особых нет
Что я изменил:

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

class CXThread : public TThread {
    private:
        void __fastcall UpdateMemo ();
        void __fastcall UpdateMemo2();

    protected:
        AnsiString StrOut;
        CXThread **BackVar;
        void __fastcall Execute();

    public:
        bool FlagWork;
        int iThreadIndex;
             __fastcall CXThread(CXThread **BackVar, bool CreateSuspended);
             __fastcall ~CXThread();
};


CXThread **BackVar;
Здесь хранится указатель на поток

bool FlagWork;
Этот флаг показывает, что основная функция потока работает. Не особо нужная вещь - просто показывает как можно ввести собственную некую индикацию состояния потока - например индикатор прогресса.

__fastcall CXThread(CXThread **BackVar, bool CreateSuspended);
В конструктор добавил параметр - адрес переменной указателя потока

AnsiString StrOut;
Украшательское поле - для разнообразия вывода.

Теперь по коду.
Код потока выглядит так:
Код

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

#include "uCXThread.h"
#include "Unit1.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall CXThread::CXThread(CXThread **pBackVar, bool CreateSuspended) :
    TThread(CreateSuspended)
{
    BackVar = pBackVar;
    FlagWork = false;
}
__fastcall CXThread::~CXThread()
{
    *BackVar = NULL;
   Synchronize(UpdateMemo2);
}
//---------------------------------------------------------------------------
void __fastcall CXThread::Execute() {
    StrOut = "Ïîòîê ðàáîòàåò";
    FlagWork = true;
    for (;;) {
        if (this->Terminated) {
            StrOut = "Ïîòîê ïðåðâàí";
         Synchronize(UpdateMemo);
            break;
        }
        Sleep(random (1000) + 500);

        Synchronize(UpdateMemo);
        if (random(200) == 100)
        {
            StrOut = "Ïîòîê çàâåðøèëñÿ";
         Synchronize(UpdateMemo);
            break;
        }
    }
    FlagWork = false;
}
//---------------------------------------------------------------------------
void __fastcall CXThread::UpdateMemo() {
    frmMain->Memo1->Lines->Add(
        "Ïîòîê ¹" + IntToStr(iThreadIndex) + " " + StrOut);
}
//---------------------------------------------------------------------------
void __fastcall CXThread::UpdateMemo2() {
    frmMain->Memo1->Lines->Add("Äåñòðóêòîð ïîòîêà_" + IntToStr(iThreadIndex));
}
//---------------------------------------------------------------------------


Я немножко модифицировал вывод - теперь поток засыпает на случайное значение, а с верофтность 0,5% при каждом цикле завершает самостоятельно свою работу.

Основная проверочная форма теперь выглядит так:
Код

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "uCXThread.h"

//#include "Units\..."
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
TfrmMain *frmMain;
const int MAX_THREADS = 50;
CXThread *pT[MAX_THREADS] = {0};
//---------------------------------------------------------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner) : TForm(Owner) {
    for (int i = 0; i < MAX_THREADS; i ++) {
        pT[i] = NULL;
    }
}
//---------------------------------------------------------------------------
__fastcall TfrmMain::~TfrmMain() {
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnRunClick(TObject *Sender) {
    Memo1->Clear();

    for (int i = 0; i < MAX_THREADS; i ++) {
        pT[i] = new CXThread(&pT[i],true);
        pT[i]->iThreadIndex    = i;
        pT[i]->FreeOnTerminate = true;
        pT[i]->Resume();
    }

    /*LOG*/Memo1->Lines->Add("--- Òðåäû çàïóùåíû ---");
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnTerminateClick(TObject *Sender) {
    for (int i = 0; i < MAX_THREADS; i ++) {
        if (NULL != pT[i]) {
            if (pT[i]->Suspended) {pT[i]->Resume();}

            pT[i]->Terminate();
        }
    }

    /*LOG*/Memo1->Lines->Add("--- Òðåäû óíè÷òîæàþòñÿ ---");
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnSuspendClick(TObject *Sender) {
    for (int i = 0; i < MAX_THREADS; i ++) {
        if (NULL != pT[i]) {
            pT[i]->Suspend();
        }
    }

    /*LOG*/Memo1->Lines->Add("--- Òðåäû ïðèîñòàíîâëåíû ---");
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnResumeClick(TObject *Sender) {
    for (int i = 0; i < MAX_THREADS; i ++) {
        if (NULL != pT[i]) {
            pT[i]->Resume();
        }
    }

    /*LOG*/Memo1->Lines->Add("--- Òðåäû âîçîáíîâëåíû ---");
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnExitClick(TObject *Sender) {
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnDeletePointersClick(TObject *Sender) {
    //íàäî ëè òàêîå äåëàòü????
    for (int i = 0; i < MAX_THREADS; i ++) {
        ////pT[i]->WaitFor();
        if (NULL != pT[i]) {
            delete pT[i];  pT[i] = NULL;
        }
    }

    /*LOG*/Memo1->Lines->Add("--- Äåñòðóêòîð ~TfrmMain ---");
}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
    //íàäî ëè òàêîå äåëàòü????
    for (int i = 0; i < MAX_THREADS; i ++) {
        //pT[i]->WaitFor();
        if (NULL != pT[i]) {
            delete pT[i];  pT[i] = NULL;
        }
    }

    /*LOG*/Memo1->Lines->Add("--- Äåñòðóêòîð ~TfrmMain ---");
}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::Button1Click(TObject *Sender)
{
    Memo2->Lines->Clear();
    for (int i=0;i<MAX_THREADS;i++)
    if (pT[i] == NULL) Memo2->Lines->Add(AnsiString(i) + ": Уничтожен");
    else
        if (pT[i]->FlagWork) Memo2->Lines->Add(AnsiString(i) + ": Работает");
        else Memo2->Lines->Add(AnsiString(i) + ": Завершен");
}
//---------------------------------------------------------------------------



Я добавил еще одно поле МЕМО и кнопку для заполнения. По этой кнопке пробегаю по списку потоков и вывожу их состояние: Работает, завершил работу, уничтожен.

Вариант "Завершил работу" будет выдан при отключенном флаге самоликвидации - поток уже отработал, но не уничтожен. Если самоликвидация включена - то по завершению функции потока он самоуничтожается и указатель на себя обнуляет.

P.S.
Что-то с русским языком при копировании кода в форум глюки - как справится?

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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

Что-то с русским языком при копировании кода в форум глюки - как справится?

Прикрепи исходники, пж.


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 20.3.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Легко



Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  ______.rar 4,46 Kb
PM MAIL ICQ   Вверх
Alca
Дата 20.3.2009, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

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



Цитата

В главной форме заводится event (CreateEvent) с ручным сбросом. При создании потока ему передают HANDLE этого event'а, от этого HANDLE поток делает DuplicateHandle и в дальнейшем ждет на нем (через WaitFor*Object). Когда дождался - закрывает свою копию HANDLE'а и завершается.
Главная форма, когда надо всех прибить, просто делает SetEvent & CloseHandle. Затем создает новый event для будущего использования

Типа так?
Код

//---------------------------------------------------------------------------
class TMyThread: public TThread {
    private:
        TEvent *FEvent;
        
    protected:
        void __fastcall Execute() {
            for (int i = 0; i < 1000; ++i) {
                std::cout << "Nice!";
            };

             FEvent->SetEvent();   //сигналим, что тред "ложиться"
        }
        
    public:
        __fastcall TMyThread(bool CreateSuspended, TEvent *Event): TThread(CreateSuspended), FEvent(Event) {
            //
        };
};
//---------------------------------------------------------------------------
int _tmain(int argc, _TCHAR *argv[]) {
    TEvent *event = new TEvent(false);
    TMyThread *thread = new TMyThread(false, event);
    
    if (event->WaitFor(10000) == wrSignaled) {
        std::cout << "END";
    } else {
        std::cout << "ERROR";
    }
    
    return 0;
}
//---------------------------------------------------------------------------


Это сообщение отредактировал(а) Alca - 26.3.2009, 00:41


--------------------
PM WWW ICQ Skype Jabber   Вверх
xvr
Дата 20.3.2009, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Не совсем.
  •  На поданном Event'е надо ждать, а не взводить его
  •  С поданного Event'а нужно сделать копию
  •  Копию надо удалять в деструкторе


PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

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


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

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


 




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


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

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