Поиск:

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


sceloglauxalbifacies
****


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

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



Цитата(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);
      }
   }

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

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


Опытный
**


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

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



Ну вот, только пометил, что вопрос решенный smile

Цитата

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


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

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

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


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

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


sceloglauxalbifacies
****


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

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



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

а... ну да.. забыл этот момент из описания задачи. а ProcessMessages то зачем? - не место ему тут.
PM MAIL   Вверх
Vyacheslav
Дата 7.12.2006, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(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];
   }





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.12.2006, 07:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

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

 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


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



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

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


Эксперт
****


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

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



Цитата(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);
);

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






--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.12.2006, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Vyacheslav
а как Handle потока получить? и что передавать в exitCode???

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



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

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


Эксперт
****


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

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



Цитата(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);
);






--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.12.2006, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



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

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

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


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

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


Эксперт
****


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

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



Код

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





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.12.2006, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



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


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

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


Эксперт
****


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

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



Код

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




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 11.12.2006, 06:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



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

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


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


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

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


Эксперт
****


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

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



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


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 11.12.2006, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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.0618 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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