Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TThread: как узнать что поток унижтожен? 
:(
    Опции темы
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   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

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


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

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


 




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


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

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