Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» ошибка в уничтожении потока Delphi+Thread+TerminateThread

Автор: OdesitVadim
Дата сообщения: 09.07.2008 12:20
а первый поток первым запускается? может он банально не даёт второму передвигать?
Как синхронизация доступа к скроллбару осуществляется?
Автор: DavidMoore
Дата сообщения: 09.07.2008 12:24
да нет всё оказалось гораздо проще
я забыл второй поток запустить в цикле он передвинул 1 раз и закрылся
Автор: VitalijUA
Дата сообщения: 02.07.2009 16:46
В продолжении этой темы.
У меня такая ситуация, нужно создать и удалить поток (всего их в последствии будет 3 различных) но так что бы при его повторном создании он не возвращался в ту точку в Execute где он был остановлен или удален.
Для примера создал небольшую программу для тестирования
В ней я поочередно меняю различного цвета image
type
TP1 = class(TThread)
protected
procedure Execute; override;
procedure Paint1;
end;
........
procedure TP1.Execute;
begin
{ Place thread code here }
i1:=0; //i1: byte;
x1:=0; //x1: integer;
y1:=0; //y1: intrger;
repeat
sleep(250);
if I1=16 then I1:=0;
Synchronize(Paint1);
sleep(1000);
x1:=5;
y1:=0;
i1:=1;
Synchronize(Paint1);
sleep(1000);
x1:=5;
y1:=0;
i1:=2;
Synchronize(Paint1);
.....//этот цикл может продолжаться очень долго, до нескольких минут
Synchronize(Paint1);
sleep(1000);
x1:=30;
y1:=15;
i1:=13;
Synchronize(Paint1);
sleep(1000);
x1:=0;
y1:=0;
inc(i1);
until Terminated;
end;

procedure TP1.Paint1;
begin
Form1.Label1.Caption:=IntToStr(I1)+' | x1:'+IntToStr(x1)+' y1:'+IntToStr(y1);
Form1.ImgList.Draw(Form1.PaintBox1.Canvas,x1,y1,i1);
end;

Для создания потока использую
if P1=nil then
begin
P1:=TP1.Create(True);
P1.Priority:=tpNormal;
P1.FreeOnTerminate:=False; //false для удаления в "ручную"
P1.Resume;
end;

Для удаления
if P1<>nil then
begin
P1.Suspend;
P1.Terminate;
P1.FreeInstance; //при Free не уничтожается
P1:=nil;
end;
так как один цикл в процедуре Execute может длится очень долго, с различными sleep по длительности и циклами while (в примере это не показанно) то автоматическое завершение при FreeOnTerminate:=true отпалает, программа приэтом подвисает т.е. ждет окончания цикла repeat. мне нужно чтобы поток Р1 завершался немедленно в любой момент времени, а при его повторном создании он начинался с начала Execute.
Удаление с помощью
P1.Suspend;
P1.Terminate; //или TerminateTread(P1.Handle,0);
FreeAndNil(P1); // не удаляет поток после этого продолжает работать пока недостигнет конца цикла.
Я почти добился этого но, возникают ситуации когда много раз удаляешь и создаешь поток Р1 он продолжает работать.
Еще такой нюанс, что программа долна будет работать на Win millenium, но для начала нужно разобратся на ХР.
Жду советов...
Автор: ShIvADeSt
Дата сообщения: 03.07.2009 00:57
VitalijUA
Фигней не майся, а запускай поток с параметрами. В зависимости от параметров делай нужные действия и после отработки завершайся. Примерно так

Код:
type
TP1 = class(TThread)
public
MyParam=byte;
protected
procedure Execute; override;
procedure Paint1;
end;


Execute..
case MyParam of
1....
2....
3....
end;

begin
P1:=TP1.Create(True);
P1.MyParam:=1 (2, 3);
P1.Priority:=tpNormal;

Автор: VitalijUA
Дата сообщения: 03.07.2009 17:25

Цитата:
Фигней не майся, а запускай поток с параметрами. В зависимости от параметров делай нужные действия и после отработки завершайся. Примерно так


Это было для примера а в реальной программе там много различных циклов и проверок
Будет выглядить так:

Код:
TP1.Execute;
repeat
sleep(5000); //от 3000 до 180000
if ...
while...
sleep( );
if ...
while...
sleep( );
while ...sleep(250);
z:=k+c-d;
while ...sleep(500);
if...;
a:=b+c-d;
if....begin while... if... while.. end;
......
buff[5]:=buff[4]-buff[j]+buff[i]
while... ;
sleep( );
while ..if ..sleep(30000);
inc();
until Terminated;
end;
Автор: delover
Дата сообщения: 06.07.2009 17:27
VitalijUA
А sleepEx можно использовать, или задержки точно вымеренные? У меня TerminateThread всегда проходит если хендл актуален. Но веть это функция! По моему приблизительно так - if TerminateThread then Thrd.Free.
Автор: Rudia
Дата сообщения: 13.07.2009 16:51
По поводу завершения потоков.
Нужно использовать метод TThread waitfor после вызова terminate - он ждет, пока произойдет выход из метода Execute (для этого метод еxecute должен завершаться по установлению terminated в true). А уже потом можно вызывать free.
Насчет FreeAndNil - это то же самое, что вызвать метод free и присвоить значение объекту nil.
А метод free - это вызов для объекта destroy c проверкой, не является ли ccылка на объект nil.
Вот если вызвать 2 раза destroy для одного объекта - дело закончится критической ошибкой.
Автор: VitalijUA
Дата сообщения: 13.07.2009 20:03

Цитата:
Нужно использовать метод TThread waitfor после вызова terminate - он ждет, пока произойдет выход из метода Execute (для этого метод еxecute должен завершаться по установлению terminated в true).

Waitfor мне не подойдет так как мне нужно НЕМЕДЛЕННОЕ завершение потока а не ждать пока процедура Execute (т.е. цикл внутри ее) отработает, она может никогда не завершиться и ожидать бесконечно!
Например там есть такие условия как:

Код: while buff[3]<>0 sleep(500);
...
sleep(50000) //от 1000 до 180000мс могут быть задержки
Автор: ShIvADeSt
Дата сообщения: 14.07.2009 02:07
VitalijUA
Почитал я тут дельфийский хелп по тридам, в общем там ни один из методом не дает 100% завершения потока. Так что мое мнение - завершай принудительно при помощи TerminateThread. Почитай хелп, что передавать и когда надо чтобы трид умер - убивай его этой функцией. Другого пути нет, так как (выдержка из хелпа)

Terminate sets the thread’s Terminated property to True, signaling that the thread should be terminated as soon as possible. Unlike the Windows API TerminateThread, which forces the thread to terminate immediately, the Terminate method merely requests that the thread terminate.
Автор: MrZeRo
Дата сообщения: 15.07.2009 15:26
VitalijUA
А разве нельзя вместо Sleep() использовать WaitForSingleObject() ? Во-первых, это менее ресурсоемкая операция (по моим наблюдениям, не претендующим на абсолютную истину), чем Sleep, во-вторых, она решает проблему прерывания потока, если использовать, например, Event или какой-нибудь другой объект (в вашем конкретном случае).

Страницы: 12

Предыдущая тема: Вопрос по FOXPRO


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.