Форум: "Основная";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
ВнизКак правильно закрыть все потоки закрывая программу? Найти похожие ветки
← →
Gear (2006-11-03 10:38) [0]Из главного потока создаю несколько, которые занимаются закачкой из сети.
Нужно чтобы при закрытии основной программы, сначала закончились все потоки, и только затем завершался главный поток программы.
Делаю так:
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;
Такую функцию вешаю на кнопку и жду завершения потоков. Но что-то всё это не работает.
Подскажие пож-та как решить правильно мою задачу?
← →
Сергей М. © (2006-11-03 10:41) [1]
> что-то всё это не работает.
Что значит "не работает" ?
← →
Gear (2006-11-03 11:01) [2]Если повесить на кнопку процедуру Term то всё работает. Но как сделать это при закрытии программы? Как узнать убились ли все потоки, а потом только разрешить закрыться программе?
← →
Ketmar © (2006-11-03 11:02) [3]у-у-у... повесь лучше какого-нибудь негра. процедуру-то за что вешать?
← →
Сергей М. © (2006-11-03 11:08) [4]
> как сделать это при закрытии программы?
Например, используя ExitProcessProc
> Как узнать убились ли все потоки
Это зависит от того как ты реализовал свой TThr
← →
Gear (2006-11-03 11:11) [5]Есть пример как надо? И в какую сторону копать?
← →
Сергей М. © (2006-11-03 11:12) [6]А с какой целью ты используешь TThreadList ?
← →
Gear (2006-11-03 11:14) [7]Только чтобы их прибить. Других способов я незнаю.
← →
Сергей М. © (2006-11-03 11:17) [8]Ну а почему, скажем, не TList и не TObjectList ?
Ведь какими-то соображениями ты, наверно, руководствовался, выбирая именно этот класс для управления списком ? Или от балды выбрал его ?)
← →
Gear (2006-11-03 11:24) [9]От балды, увидел пример и всё.
← →
Сергей М. © (2006-11-03 11:26) [10]Ну плохо что от балды)
Какое макс.число потоков может существовать у тебя ?
← →
Gear (2006-11-03 11:29) [11]не более 5-10
← →
Сергей М. © (2006-11-03 11:30) [12]Чему равно св-во FreeOnTerminate ?
← →
Gear (2006-11-03 11:34) [13]constructor TThr.Create(uri:TStringList);
begin
inherited Create(True);
Form1.ThreadList.Add(Self);
Furi:=Tstringlist.Create;
Furi.AddStrings(rssuri);
FreeOnTerminate:=True;
resume;
end;
← →
Сергей М. © (2006-11-03 11:48) [14]constructor TThr.Create(uri:TStringList);
begin
inherited Create(True);
...
Form1.ThreadList.Add(Self);
...
end;
destructor TThr.Destroy; //override !
begin
..
inherited;
Form1.ThreadList.Remove(Self);
..
end;
...
with ThreadList.LockList do
try
for i := 0 to Count - 1 do
TThr(Items[i]).Terminate;
finally
UnlockList
end;
while True do
with ThreadList.LockList do
try
if Count = 0 then Break;
finally
UnlockList
end;
← →
Gear (2006-11-03 12:07) [15]вот до этого места
while True do
with ThreadList.LockList do
try
if Count = 0 then Break;
finally
UnlockList
end;
у меня всё так.
Куда вот это?
← →
Сергей М. © (2006-11-03 12:33) [16]Вот именно туда куда я написал, т.е. непосредственно следом за
with ThreadList.LockList do
try
for i := 0 to Count - 1 do
TThr(Items[i]).Terminate;
finally
UnlockList
end;
← →
Gear (2006-11-03 12:59) [17]хорошо, а это всё вешать на OnClose?
← →
Gear (2006-11-03 13:03) [18]Программа виснет. Видимо в цикле
while True do
with ThreadList.LockList do
try
if Count = 0 then Break;
finally
UnlockList
end;
sleep(1000) не помогает
← →
Дмитрий Белькевич © (2006-11-03 13:18) [19]>Программа виснет. Видимо в цикле
Так посмотри, там или нет - бряк не долго поставить.
Если там, то собсно у тебя Terminate не проходит в каком-то или во всех потоках, соответственно, Count всегда больше нуля.
← →
Сергей М. © (2006-11-03 13:21) [20]
> sleep(1000) не помогает
Это из другой оперы.
Если "виснет", то это означает, что как минимум один из твоих потоков завершаться упорно не желает.
← →
Gear (2006-11-03 13:35) [21]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:56) [22]
> Terminate проходит
А куда он денется ?
Метод Terminate не занимается ничем иным, кроме как взведением флажка FTerminated.
> вижу что они сносятся.
Значит никаких проблем с "залоченностью" нет.
> Тем самым циклом этот список залочен
Каким "тем" ?
Этим что ли
while True do
with ThreadList.LockList do
try
if Count = 0 then Break;
finally
UnlockList
end;
?
Ну ты ж видишь, что блокировка-разблокировка происходит в каждой итерации цикла, а длится каждая итерация тысячные доли секунды.
Так что не надо выдумывать небылицы - лучше приводи код метода TThr.Execute
← →
Percent (2006-11-03 14:48) [23]Thread.Terminate;
Thread.WaitFor;
Tread.Free;
← →
Сергей М. © (2006-11-03 14:54) [24]
> Percent (03.11.06 14:48) [23]
> Tread.Free;
см. [13], 3-я строчка снизу
← →
Gear (2006-11-03 16:30) [25]Легко могу даже весь код маленького проекта:
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 16:40) [26]
> Gear (03.11.06 16:30) [25]
ты хоть что-нть слышал о небезопасности мультипоточного обращения к VCL-объектам ?
← →
Джо © (2006-11-03 16:43) [27]> [25] Gear (03.11.06 16:30)
> Легко могу даже весь код маленького проекта:
Небольшое замечание. Следует сказать так:
"Легко могу даже весь код маленького неработающего проекта".
← →
Gear (2006-11-03 17:05) [28]Наверное не слышал. Что там не так?
← →
Сергей М. © (2006-11-03 17:09) [29]
> Что там не так?
Низя.
на то есть метод TThread.Synchronize()
← →
Gear (2006-11-03 17:17) [30]да, это я так, забыл малость, но дело-то не в этом.
← →
Сергей М. © (2006-11-03 17:20) [31]
> дело-то не в этом.
Сначала устрани явные ляпы, потоми и разговор будет предметный.
← →
Gear (2006-11-03 17:32) [32]Это сделано.
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-04 02:32) [33]> While not Terminated do begin
1. этот цикл вообще крутиться?
2. Когда нажал на кнопку останова, Terminated взводится? Цикл останавливается?
← →
Сергей М. © (2006-11-04 10:38) [34]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;
← →
TStas © (2006-11-04 17:39) [35]Ой, а подскажите чайнику: разьве потоки не умирают естественной смертью при завершении программы?
← →
Leonid Troyanovsky © (2006-11-04 18:07) [36]
> TStas © (04.11.06 17:39) [35]
> Ой, а подскажите чайнику: разьве потоки не умирают естественной
> смертью при завершении программы?
Дык, а где уверенность, что она завершена?
Процесс жив, пока живет последний из потоков.
Кста, в 95 бывало, что потоки переживали и процесс.
Хотя, 2006 им-то уж не пережить.
--
Regards, LVT.
← →
guav © (2006-11-04 19:13) [37]> [35] TStas © (04.11.06 17:39)
При завершении первичного потока "естественным" путём (завершением выполннения блока begin...end программы или halt), из RTL будет вызвана ExitProcess, все остальные потоки будут завершены.
← →
Gear (2006-11-06 02:04) [38]Они то завершатся, а вот с памятью его что-то станется. Вернее не освободится правильно. Поэтому-то и весь сырбор.
← →
Gear (2006-11-06 02:10) [39]Да, всем спасибо, особенно Сергею М. Получилось то, что надо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.043 c