Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.10.08;
Скачать: CL | DM;

Вниз

Остановка потока   Найти похожие ветки 

 
Destroyer ©   (2006-08-26 21:28) [0]

Задача выполняется в потоке. По нажатию кнопки на форме надо остановить выполнение потока. Проверять флаг постоянно на отключение - не подходит. Нужно что-то типа TimerThread.Destroy.
Делаю так:

protected
   procedure Execute; override;
 public
 constructor Create(FPath: String; Fflag: boolean; RProcType:string; FExt:string);
 constructor Destroy;
 end;

...
constructor TimerThread.Destroy;
begin
exit;
end;
Но так, выдается ошибка неверный дескриптор.
Как правильно мгновенно остановить поток?


 
Ketmar ©   (2006-08-26 21:29) [1]

правильно -- проверять флаг.


 
DVM ©   (2006-08-26 21:34) [2]


> Проверять флаг постоянно на отключение - не подходит

именно это самый быстрый и корректный путь.


> Как правильно мгновенно остановить поток?

Мгновенно, но не всегда правильно TerminateThread()


 
Fay ©   (2006-08-26 22:18) [3]

> constructor Create(FPath: String; Fflag: boolean; RProcType:string; FExt:string);
> constructor Destroy;
Это просто бред


 
Ketmar ©   (2006-08-26 22:20) [4]

> [3] Fay ©   (26.08.06 22:18)
вах! а я и не заметил. %-)


 
Destroyer ©   (2006-08-26 23:06) [5]

BOOL TerminateThread(

   HANDLE hThread, // handle to the thread
   DWORD dwExitCode  // exit code for the thread
  );
Где взять хэндл потока?
Поток создается так:
TimerThread.Create(dir1,false,"Param1",Ext);


 
Чапаев носками хакера   (2006-08-26 23:30) [6]

> Где взять хэндл потока?

OpenThread(). Подробности в справке.


 
Destroyer ©   (2006-08-27 01:02) [7]

Извините, конечно, но все что нашось в справке - OpenThread() that takes a thread ID and returns a thread handle. А где ID взфть?
Также говорится, что хэндл получается при создании потока.
CreateThread() API is used to create threads.
Но у меня поток создается способом см. выше. Может из него как-то хэндл взять?


 
Германн ©   (2006-08-27 01:46) [8]


> Но у меня поток создается способом см. выше. Может из него
> как-то хэндл взять?

А что тогда есть
> TimerThread
?
Я такого не знаю. Чей он потомок?


 
Чапаев носками хакера   (2006-08-27 08:54) [9]

> Извините, конечно, но все что нашось в справке - OpenThread()
> that takes a thread ID and returns a thread handle. А где
> ID взфть?

Если поток твой, тебе лучше знать, какой у него TID. Если чужой, смотри справку по CreateToolhelp32Snapshot(), а дальше по ссылкам.


 
begin...end ©   (2006-08-27 09:02) [10]

> Чапаев носками хакера   (26.08.06 23:30) [6]

TThread.Handle. Подробности в справке.


 
Destroyer ©   (2006-08-27 14:32) [11]

Германн,
type
 TimerThread = class(TThread)
begin...end,
В справке есть.
Indicates the thread"s handle (Windows only).
Delphi syntax:
property Handle: THandle;
Видимо, то что нужно.
Но компилятор не принимает, ошибка: Method identifier expected.


 
y-soft ©   (2006-08-27 22:06) [12]

>Destroyer ©   (26.08.06 23:06) [5]

Не используйте TerminateThread, это чревато многими неприятностями и используется в самых крайних аварийных случаях

Самое правильное и простое в Вашем случае - установить при создании TTimerThread
FreeOnTerminate := True и периодически проверять флаг. Когда функция потока обнаружит, что флаг установлен - просто выходить из функции потока. Тогда и хендл потока Вам не понадобится

Другого корректного (а тем более "мгновенного" способа) в общем случае просто не существует (хотя могут и быть варианты в зависимости от того, чем конкретно занимается поток. Например, можно мгновенно отменить все операции ввода/вывода для файлового устройства, закрыв все открытые хендлы этого устройства)


 
DVM ©   (2006-08-27 22:08) [13]


> FreeOnTerminate := True

Крайне глюконосная фича.


 
y-soft ©   (2006-08-27 22:12) [14]

>DVM ©   (27.08.06 22:08) [13]

TThread в Delphi вообще написан довольно криво :(
Но в большинстве случаев все работает


 
Ketmar ©   (2006-08-27 22:15) [15]

поркзаная цитата из генофонда:
function ThreadProc(Thread: TThread): Integer;
var
 FreeThread: Boolean;
begin
 try
   if not Thread.Terminated then
   try
     Thread.Execute;
   except
     Thread.FFatalException := AcquireExceptionObject;
   end;
 finally
   FreeThread := Thread.FFreeOnTerminate;
   Result := Thread.FReturnValue;
   Thread.DoTerminate;
   Thread.FFinished := True;
   SignalSyncEvent;
   if FreeThread then Thread.Free;
   EndThread(Result);
 end;
end;


если писать корректно и не совершать страшного в OnTerminate(), то никаких глюков не вижу.


 
y-soft ©   (2006-08-27 22:18) [16]

>DVM ©   (27.08.06 22:08) [13]

FreeOnTerminate предполагает, что судьба потока после завершения неинтересна - завершился и самоуничтожился. Для того, чтобы избежать глюков следует отловить завершение потока (например, с помощью WaitForXXX) и обнулить указатели на него


 
DVM ©   (2006-08-27 22:23) [17]


> Для того, чтобы избежать глюков следует отловить завершение
> потока

Я бы советовал в любом случае это делать.


 
y-soft ©   (2006-08-27 22:25) [18]

>DVM ©   (27.08.06 22:23) [17]
Я бы советовал в любом случае это делать

Конечно, если есть хотя бы один указатель на него и существует вероятность, что к нему возможно обращение


 
Пусик ©   (2006-08-27 22:27) [19]


> DVM ©   (27.08.06 22:08) [13]
>
> > FreeOnTerminate := True
>
> Крайне глюконосная фича.


Это еще почему?
Вряд ли она ВООБЩЕ хоть чуть-чуть глюконосная.


> y-soft ©   (27.08.06 22:12) [14]
>
> TThread в Delphi вообще написан довольно криво :(


А что в нем кривого особо?


 
DVM ©   (2006-08-27 22:29) [20]


> Вряд ли она ВООБЩЕ хоть чуть-чуть глюконосная.

Глюки не в ней, а в неправильном ее использовании. Иногда даже и не подумаешь, что проблемы именно в ней.


 
y-soft ©   (2006-08-27 22:31) [21]

>Пусик ©   (27.08.06 22:27) [19]

А что в нем кривого особо?

ОСОБО кривого нет. Есть отдельные недодуманности. Например метод Synchronize - основная причина тормозов в многопоточных программах начинающих :)

Вообще, начиная с Windows 2000 появилась прекрасная альтернатива TThread в большинстве случаев - системный пул потоков


 
Пусик ©   (2006-08-27 22:34) [22]


> y-soft ©   (27.08.06 22:31) [21]
> >Пусик ©   (27.08.06 22:27) [19]
>
> А что в нем кривого особо?
>
> ОСОБО кривого нет. Есть отдельные недодуманности. Например
> метод Synchronize - основная причина тормозов в многопоточных
> программах начинающих :)
>
> Вообще, начиная с Windows 2000 появилась прекрасная альтернатива
> TThread в большинстве случаев - системный пул потоков


Да, альтернатива есть, но как раз начинающим использование пула потоков рекомендовать нельзя слишком сложно для использования. Да и вряд ли у начинающих возникнут задачи, требующие подобного решения.


 
Ketmar ©   (2006-08-27 22:36) [23]

> [21] y-soft ©   (27.08.06 22:31)
интересно, каким боком Synchronuze() относится к реализации TThread? это, вообще-то, проблема VCL.


 
y-soft ©   (2006-08-27 22:37) [24]

>Пусик ©   (27.08.06 22:34) [22]

...но как раз начинающим использование пула потоков рекомендовать нельзя слишком сложно для использования

IMHO намного проще получается, чем с TThread, но программирование действительно сложное занятие, особенно профессиональное :)


 
DVM ©   (2006-08-27 22:40) [25]


> интересно, каким боком Synchronuze() относится к реализации
> TThread? это, вообще-то, проблема VCL.

A TThread не из VCL что ли?


 
y-soft ©   (2006-08-27 22:40) [26]

>Ketmar ©   (27.08.06 22:36) [23]

Проблема в том, что не предусмотрено метода Asynchronize :)


 
Пусик ©   (2006-08-27 22:46) [27]


> y-soft ©   (27.08.06 22:40) [26]
> >Ketmar ©   (27.08.06 22:36) [23]
>
> Проблема в том, что не предусмотрено метода Asynchronize
> :)


Ну как раз реализация асинхронной синхронизации не представляет сложности;)


 
y-soft ©   (2006-08-27 22:59) [28]

>Пусик ©   (27.08.06 22:46) [27]

Безопасная реализация достаточна сложна. Начинающему явно не по зубам

Хотя... Можно, например, сделать так:
http://y-soft.comsignal.ru/Delphi/ThreadX_pas.html (просьба сильно не пинать) :)


 
Ketmar ©   (2006-08-27 23:03) [29]

> [27] Пусик ©   (27.08.06 22:46)
> асинхронной синхронизации
не надо так шутить на ночь глядя. %-)


 
Slym ©   (2006-08-28 04:43) [30]

Мой пинок в бочину TThread - Terminate - не виртуальный, как хочется в него чегонибудь добавить, например обрыв синхронных вызовов


 
Fay ©   (2006-08-28 04:51) [31]

2 Slym ©   (28.08.06 4:43) [30]
> Terminate - не виртуальный, как хочется в него
> чегонибудь добавить, например обрыв синхронных вызовов
Коран не запрещает завернуть Terminate в свой метод


 
Ketmar ©   (2006-08-28 05:00) [32]

равно как сделать обработчик события OnTerminate().


 
Slym ©   (2006-08-28 10:14) [33]

Fay ©   (28.08.06 4:51) [31]
Коран не запрещает завернуть Terminate в свой метод

А дальнейшее приведение типа TThread(Thread).Terminate? или сунуть руки в генофонд?


 
Slym ©   (2006-08-28 10:18) [34]

Ketmar ©   (28.08.06 5:00) [32]
обработчик события OnTerminate()

сработает после выхода из процедуры потока...
прерывать синхронный вызов в OnTerminate бессмысленно, т.к. он уже отвалился сам. вот еслиб был OnBeforeTerminate


 
Ketmar ©   (2006-08-28 10:43) [35]

> [34] Slym ©   (28.08.06 10:18)
> сработает после выхода из процедуры потока...
и в чём проблема, если всё равно создаётся класс-потомок? нужные переменные -- в поля.

> прерывать синхронный вызов
это что такое? поподробней можно?


 
Ketmar ©   (2006-08-28 10:43) [36]

> [33] Slym ©   (28.08.06 10:14)
"завернуть" и "перекрыть" -- вещи разные.


 
BiN ©   (2006-08-28 10:47) [37]

Любые высказывания в сторону кажущейся кривости реализации TThread необоснованны и посему - бред.
имо.


 
isasa ©   (2006-08-28 10:53) [38]

:)
В общем, отсюда вывод, юзаем CreateThread (для фанатов BeginThread).


 
y-soft ©   (2006-08-28 10:55) [39]

>BiN ©   (28.08.06 10:47) [37]

Несколько безаппеляционно сказано. IMHO, конечно :)


 
isasa ©   (2006-08-28 10:58) [40]

Slym ©   (28.08.06 04:43) [30]
.... как хочется в него чегонибудь добавить, например обрыв синхронных вызовов


Для таких случаев даден флаг Terminated, что-бы нормально разрулить логику внутри метода Execute. Конечно, если сносить поток шашкой (TerminateThread), то тогда все равно. :)


 
Ketmar ©   (2006-08-28 11:00) [41]

> [38] isasa ©   (28.08.06 10:53)
не для фанатов, а для менеджера памяти. %-)


 
y-soft ©   (2006-08-28 11:01) [42]

>Ketmar ©   (28.08.06 11:00) [41]

И для правильной обработки исключений


 
BiN ©   (2006-08-28 11:02) [43]


> y-soft ©   (28.08.06 10:55) [39]
>
> Несколько безаппеляционно сказано. IMHO, конечно :)


Ок, аппеляции:


> y-soft ©   (27.08.06 22:31) [21]
>
> >Пусик ©   (27.08.06 22:27) [19]
>
> А что в нем кривого особо?
>
> ОСОБО кривого нет. Есть отдельные недодуманности. Например
> метод Synchronize - основная причина тормозов в многопоточных
> программах начинающих :)


Виноват кто? Ну, конечно же, TThread. Не начинающие же.


 
Ketmar ©   (2006-08-28 11:06) [44]

> [42] y-soft ©   (28.08.06 11:01)
а исключения без менеджера памяти не живут. %-)


 
y-soft ©   (2006-08-28 11:08) [45]

>BiN ©   (28.08.06 11:02) [43]

Инструмент, конечно, не виноват, повторюсь: ОСОБО кривого нет, написано добротно.  Виноваты кривые руки. Только вот всегда есть выбор - есть, что дают, или приготовить самому, если не устраивает


 
Ketmar ©   (2006-08-28 11:10) [46]

> [45] y-soft ©   (28.08.06 11:08)
конечно, выбор есть. но если кто-то не любит селёдку, это не причина ругать повара?


 
y-soft ©   (2006-08-28 11:11) [47]

>Ketmar ©   (28.08.06 11:06) [44]
> [42] y-soft ©   (28.08.06 11:01)
а исключения без менеджера памяти не живут. %-)


Unhandled exceptions еще как живут и побеждают с криком: "Ваше приложение выполнило недопустимую операцию и будет закрыто" :)


 
Ketmar ©   (2006-08-28 11:12) [48]

> [47] y-soft ©   (28.08.06 11:11)
а мы их напугаем SetUnhandledExceptionFilter()"ом. %-)


 
y-soft ©   (2006-08-28 11:12) [49]

>Ketmar ©   (28.08.06 11:10) [46]

Не повара, а блюдо


 
y-soft ©   (2006-08-28 11:14) [50]

>Ketmar ©   (28.08.06 11:12) [48]

а мы их напугаем SetUnhandledExceptionFilter()"ом. %-)

Ну, ежели охота в такие глубины лезть :)


 
Slym ©   (2006-08-28 12:02) [51]

Ketmar ©   (28.08.06 10:43) [35]
> прерывать синхронный вызов
это что такое? поподробней можно?

procedure TxThread.Execute;
begin
 while not terminated do
   Event.WaitFor(INFINITY);
end;

еслиб procedure TThread.Terminate; был virtual яб его

procedure TxThread.Terminate; override;
begin
 inherited;
 Event.Signal;
end;


 
Ketmar ©   (2006-08-28 12:11) [52]

ну напиши свой класс. там кода-то...


 
Slym ©   (2006-08-28 14:05) [53]

сделай так чтоб этот код выполнялся менее секунды :)
ограничения:
1. публиковать Event низя, или иначе управлять им не из TxThread
program Project1;
{$APPTYPE CONSOLE}
uses classes,SyncObjs,Windows;
type
 TxThread=class(TThread)
 private
   Event:TSimpleEvent;
 protected
   procedure Execute;override;
 public
   constructor Create(CreateSuspended: Boolean);
   destructor Destroy; override;
 end;

constructor TxThread.Create(CreateSuspended: Boolean);
begin
 Event:=TSimpleEvent.Create;
 inherited;
end;

destructor TxThread.Destroy;
begin
 inherited;
 Event.Free;
end;

procedure TxThread.Execute;
begin
 repeat
   Event.WaitFor(60000);
   writeln("loop :)");
 until terminated;
end;

var x:TxThread;
begin
 x:=TxThread.Create(false);
 sleep(0);
 x.Free;
 writeln("Final!");
end.


 
Ketmar ©   (2006-08-28 14:32) [54]

> [53] Slym ©   (28.08.06 14:05)
и не подумаю. ибо если мне нужны такие условия, то я буду думать над переделкой кода, а не над тем, как вилами геморрой лечить. %-)


 
Slym ©   (2006-08-29 04:34) [55]

Ketmar ©   (28.08.06 14:32) [54]
ибо если мне нужны такие условия

ИнкапсЮляция батенька :)


 
Ketmar ©   (2006-08-29 09:47) [56]

> [55] Slym ©   (29.08.06 04:34)
нет. апофигеоз. %-)


 
Destroyer ©   (2006-08-30 16:11) [57]

Такой вопрос. Нужно выполнять действие, в данном случае деактивировать кнопку на главной форме, при каждом завершении потока. Что-то типа события OnTerminate. Подскажите как такое осуществить.


 
Dmitrij_K   (2006-08-30 16:14) [58]

OnTerminate не подходит?


 
Destroyer ©   (2006-08-30 16:21) [59]

А как с OnTerminate?
Вот решил эту проблему так:
...
 public
 destructor Destroy; override;
...
destructor TimerThread.Destroy;
begin
inherited;
MainForm.StopOperationButton.Enabled:=false;
end;


 
Reindeer Moss Eater ©   (2006-08-30 16:22) [60]

Какого только бреда не придумают, только чтобы не думать головой.


 
Dmitrij_K   (2006-08-30 16:25) [61]

Thread.OnTerminate := твоё
сникерсни Ж)


 
Reindeer Moss Eater ©   (2006-08-30 16:26) [62]

Создай поток, передай ему хендл главного окна.
Если собираешься прибивать поток снаружи сохрани хендл потока.
В конце Execute пошли сообщение хендлу окна.
В обработчике сообщения главного окна прими сообщение.
И все.


 
y-soft ©   (2006-08-30 17:51) [63]

>Reindeer Moss Eater ©   (30.08.06 16:26) [62]

С Вашего позволения дополню

Именно главного окна (Application.Handle), а не главной формы, и обрабатывать в Application.OnMessage... И использовать PostMessage


 
Reindeer Moss Eater ©   (2006-08-30 18:42) [64]

разницы-то вроде никакой


 
y-soft ©   (2006-08-30 20:21) [65]

>Reindeer Moss Eater ©   (30.08.06 18:42) [64]

Из условия не видно, что пользователь не может произвести действия, которые вызовут, например,  RecreateWnd для главной формы, и в конечном итоге изменят хендл ее окна. С окном приложения такого точно не произойдет



Страницы: 1 2 вся ветка

Текущий архив: 2006.10.08;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.031 c
15-1158474454
ramor
2006-09-17 10:27
2006.10.08
Модуль программиста в Delphi


2-1158708747
Павел_
2006-09-20 03:32
2006.10.08
Потоко-безопасная запиcь в файл.


8-1142340920
antoxa2005
2006-03-14 15:55
2006.10.08
Мастера. Подскажите, как "отрисовать" bmp изображение поверх TIma


15-1158582991
wwwrr
2006-09-18 16:36
2006.10.08
Memo + Анимация


1-1156858042
DFil
2006-08-29 17:27
2006.10.08
Потоки и их организация...