Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как правильно закрыть все потоки закрывая программу? [D7, WinXP]


Страницы:   1 2

Gear ©   (2006-11-03 10:38:00) 

Из главного потока создаю несколько, которые занимаются закачкой из сети.
Нужно чтобы при закрытии основной программы, сначала закончились все потоки, и только затем завершался главный поток программы.
Делаю так:
1) В потоках делаю что-то типа
While not Terminated do begin
end;
2) Держу ThreadList и имею функцию что-то типа:

procedure TForm1.Term;
var
 i:integer;
begin
  with ThreadList, LockList do
   try
      for i := 0 to Count - 1 do
      begin
         TThr(Items[i]).Terminate;
      end;
   finally
     UnlockList
   end;
end;

Такую функцию вешаю на кнопку и жду завершения потоков. Но что-то всё это не работает.
Подскажие пож-та как решить правильно мою задачу?


Gear   (2006-11-06 02:10:00) [1]

Да, всем спасибо, особенно Сергею М. Получилось то, что надо!


Gear   (2006-11-06 02:04:00) [2]

Они то завершатся, а вот с памятью его что-то станется. Вернее не освободится правильно. Поэтому-то и весь сырбор.


guav   (2006-11-04 19:13:00) [3]

> [35] TStas ©   (04.11.06 17:39)


При завершении первичного потока "естественным" путём (завершением выполннения блока begin...end программы или halt), из RTL будет вызвана ExitProcess, все остальные потоки будут завершены.


Leonid Troyanovsky   (2006-11-04 18:07:00) [4]


> TStas ©   (04.11.06 17:39) [35]
> Ой, а подскажите чайнику: разьве потоки не умирают естественной
> смертью при завершении программы?


Дык, а где уверенность, что она завершена?
Процесс жив, пока живет последний из потоков.

Кста, в 95 бывало, что потоки переживали и процесс.
Хотя, 2006 им-то уж не пережить.

--
Regards, LVT.


TStas   (2006-11-04 17:39:00) [5]

Ой, а подскажите чайнику: разьве потоки не умирают естественной смертью при завершении программы?


Сергей М.   (2006-11-04 10:38:00) [6]

procedure TForm1.Term;
var
i:integer;
begin
 with ThreadList, LockList do
  try
     for i := 0 to Count - 1 do
     begin
        TThr(Items[i]).Terminate;
     end;
  finally
    UnlockList
  end;

 while True do begin
   with ThreadList.LockList do
   try
      if Count = 0 then
        Break
      else
        Application.ProcessMessages;
   finally
     UnlockList
   end;
 end;
end;


Дмитрий Белькевич   (2006-11-04 02:32:00) [7]

> While not Terminated do begin
1. этот цикл вообще крутиться?
2. Когда нажал на кнопку останова, Terminated взводится? Цикл останавливается?


Gear   (2006-11-03 17:32:00) [8]

Это сделано.

procedure TThr.Execute;
...
Synchronize(Form1.trm);
...
Synchronize(Form1.html);
...

procedure TForm1.html;
begin
 Form1.Memo1.Lines.Add('html');
end;

procedure TForm1.trm;
begin
 Form1.Memo1.Lines.Add('term');
end;

Что ещё не так?


Сергей М.   (2006-11-03 17:20:00) [9]


> дело-то не в этом.


Сначала устрани явные ляпы, потоми и разговор будет предметный.


Gear   (2006-11-03 17:17:00) [10]

да, это я так, забыл малость, но дело-то не в этом.


Сергей М.   (2006-11-03 17:09:00) [11]


> Что там не так?


Низя.

на то есть метод TThread.Synchronize()


Gear   (2006-11-03 17:05:00) [12]

Наверное не слышал. Что там не так?


Джо   (2006-11-03 16:43:00) [13]

> [25] Gear   (03.11.06 16:30)
> Легко могу даже весь код маленького проекта:

Небольшое замечание. Следует сказать так:
"Легко могу даже весь код маленького неработающегопроекта".


Сергей М.   (2006-11-03 16:40:00) [14]


> Gear   (03.11.06 16:30) [25]


ты хоть что-нть слышал о небезопасности мультипоточного обращения к VCL-объектам ?


Gear   (2006-11-03 16:30:00) [15]

Легко могу даже весь код маленького проекта:


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, httpsend, ExtCtrls;

type
 TThr= class(TThread)
  private
  protected
  procedure Execute; override;
 public
  Furi:TstringList;
  constructor Create(uri:TstringList);
  destructor Destroy; override;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   Button2: TButton;
   Timer1: TTimer;
   ListBox1: TListBox;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
   Thr:TThr;
   ThreadList: TThreadList;
   procedure Term;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
rssuri:TStringList;
begin
rssuri:=TStringList.Create;
rssuri.Add(' http://www.ya.ru');
rssuri.Add(' http://www.mail.ru');
rssuri.Add(' http://www.rambler.ru');
Thr:=TThr.Create(uri);
uri.free;
end;

constructor TThr.Create(uri:TStringList);
begin
inherited Create(True);
Form1.ThreadList.Add(Self);
Furi:=Tstringlist.Create;
Furi.AddStrings(uri);
FreeOnTerminate:=True;
resume;
end;

destructor TThr.Destroy;
begin
if Furi<>nil then
 begin
  Furi.Free;
  Furi:=nil;
 end;
 Form1.ThreadList.Remove(Self);
 inherited Destroy;
end;

procedure TThr.Execute;
var
 s,uri:TStringList;
 HTTP : THTTPSend;
 good: boolean;
 k:integer;
begin
 s:=TStringList.Create;

 While not Terminated do begin

 for k:=0 to Frssuri.Count-1 do
 begin
      HTTP := THTTPSend.Create;
      HTTP.Protocol:='1.1';
      try
        good:=HTTP.HTTPMethod('GET',Furi.Strings[k]);
        if good then
           s.LoadFromStream(HTTP.Document);
      finally
         HTTP.Free;
         HTTP:=nil;
      end;
      Form1.Memo1.Lines.Add('html');
      if Terminated then
      begin
        Form1.Memo1.Lines.Add('term');
        break;
      end;
 end;
 sleep(1000);
 end;
 s.free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ThreadList:= TThreadList.Create;
end;

procedure TForm1.Term;
var
 i:integer;
begin
  with ThreadList, LockList do
   try
      for i := 0 to Count - 1 do
      begin
         TThr(Items[i]).Terminate;
      end;
   finally
     UnlockList
   end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Term;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
i:integer;
id:string;
begin
 listbox1.Clear;
 with ThreadList, LockList do
 try
   for i := 0 to Count - 1 do
   begin
     id := inttostr(TThr(Items[i]).ThreadID);
     listbox1.Items.Add(id);
   end;
 finally
   UnlockList
 end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ThreadList.Free;
end;

end.


Коммент к коду:
1) нажимаю button1, плодится поток который загружает html и отчитывается об этом в memo1.
2) Button2 терминирует все процессы и отчитывается словом term в тот же memo1.
3) По таймеру оббегается весь тредлист и id процессов выводит в listbox1.
Вот и вся программка.


Сергей М.   (2006-11-03 14:54:00) [16]


> Percent   (03.11.06 14:48) [23]


> Tread.Free;


см. [13], 3-я строчка снизу


Percent   (2006-11-03 14:48:00) [17]

Thread.Terminate;
Thread.WaitFor;
Tread.Free;


Сергей М.   (2006-11-03 13:56:00) [18]


> Terminate проходит


А куда он денется ?

Метод Terminate не занимается ничем иным, кроме как взведением флажка FTerminated.


> вижу что они сносятся.


Значит никаких проблем с "залоченностью" нет.


> Тем самым циклом этот список залочен


Каким "тем" ?

Этим что ли

while True do
with ThreadList.LockList do
try
   if Count = 0 then Break;
finally
  UnlockList
end;

?

Ну ты ж видишь, что блокировка-разблокировка происходит в каждойитерации цикла, а длится каждая итерация тысячные доли секунды.

Так что не надо выдумывать небылицы - лучше приводи код метода TThr.Execute


Gear   (2006-11-03 13:35:00) [19]

Terminate проходит, если вот это повесить на кнопку
with ThreadList.LockList do
 try
    for i := 0 to Count - 1 do
       TThr(Items[i]).Terminate;
 finally
   UnlockList
 end;

и вывести куда-нибудь список threadid то я вижу что они сносятся.
Я думаю просто в тот момент когда происходит Form1.ThreadList.Remove(Self);
Тем самым циклом этот список залочен. И программа виснет.


Сергей М.   (2006-11-03 13:21:00) [20]


> sleep(1000) не помогает


Это из другой оперы.

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо