Форум: "WinAPI";
Текущий архив: 2002.01.31;
Скачать: [xml.tar.bz2];
ВнизTHREADS !!! Найти похожие ветки
← →
Evgeniy_S (2001-11-28 16:13) [0]блин, я уже запарился :(( помогите плиз разобраться с такой фигней (можно сказать чисто спортивный интерес, самое интересное, что в одной проге это работает, а при попытке повторения этого дела в других прогах отказывается! )
есть такое описание :
const
wm_stop_thread = wm_user + 2;
type
Thread = class (TThread)
protected
procedure execute;override;
procedure stop (var Msg : TMessage); message wm_stop_thread;
procedure UpdateCaption;
end;
procedure THread.execute;
begin
//делаем что то долго, циклов тут нет...
end;
procedure THread.stop(var Msg: TMessage);
begin
case Msg.WParam of
0 : Suspend;
1 : Resume;
2 : Terminate;
end;
end;
//создаем тред
procedure TForm1.Button1Click(Sender: TObject);
begin
with Thread.Create(true) do
begin
Form1._Handle := Handle;
resume;
end;
end;
//посылаем ему команду, чтоб он умер, но нифига не получется,
//хотя, повторюсь в уже написанной проге так работает!
procedure TForm1.Button2Click(Sender: TObject);
begin
PostMessage(_Handle, wm_stop_thread, 2, 0);
//SendMessage и PostThreadMessage дают тот же результат
end;
← →
troits (2001-11-28 16:41) [1]Посмотри на реализацию terminate. Там просто выставляется флаг.
Ты уж сам должен выходить из Execute, если этот флаг выставлен.
← →
Evgeniy_S (2001-11-28 16:54) [2]ну если бы в екзекуте у меня було:
repeat
...
until terminated
тогда да, но нету у меня там циклов, это во первых во вторых смотри выше, эта фигня уменя уже в откомпиленом проекте работает, просто повторить не получется почему то ...
← →
troits (2001-11-28 17:30) [3]Подожди, я повнимательней посмотрел на твой код, и
не понял, как ты собираешься вызывать procedure stop.
TThread - это не окно.
← →
Digitman (2001-11-28 17:32) [4]
const
const tm_terminate_thread = wm_user + ...;
type
TMyThread = class (TThread)
...
protected
...
procedure execute;override;
...
public
destructor Destroy; override;
end;
TForm1 = class(TForm)
...
public MyThread: Thread
...
end;
implementation
destructor TMyThread.Destroy;
begin
if not Suspended then
PostThreadMessage(ThreadId, tm_terminate_thread, 0, 0);
inherited Destroy;
end;
procedure TMyThread.Execute;
begin
if not Terminated and not PeekMessage(0, tm_terminate_thread, 0, 0, PM_REMOVE) then
SomeShortStatementSequence1
else
Exit;
if not Terminated and not PeekMessage(0, tm_terminate_thread, 0, 0, PM_REMOVE) then
SomeShortStatementSequence2
else
Exit;
if not Terminated and not PeekMessage(0, tm_terminate_thread, 0, 0, PM_REMOVE) then
SomeShortStatementSequenceN
else
Exit;
//... и т.д., раз уж цикл не устраивает
end;
procedure TForm1.CreateSuspendedThreadButtonClick(Sender: TObject);
begin
MyThread := TMyThread.Create(true);
end;
procedure TForm1.SuspendThreadButtonClick(Sender: TObject);
begin
MyThread.Suspend;
end;
procedure TForm1.ResumeThreadButtonClick(Sender: TObject);
begin
MyThread.Resume;
end;
procedure TForm1.SafeTerminateThreadButtonClick(Sender: TObject);
begin
MyThread.Free;
end;
procedure TForm1.KillThreadButtonClick(Sender: TObject);
begin
MyThread.Suspend;
MyThread.Free;
end;
← →
Evgeniy_S (2001-11-28 17:43) [5]>troits ©
дык ведь фунциклирует как то ...
>Digitman ©
спасибо за обширный ответ, но суть не в том , что меня цикл не устраивает, я бы его с радостью запихнул, да некуда, просто я в треде тяну страницу, и делаю соответственно HTTP.Get(url), (пользую я для этого indy), и пока он ее не вытянт, код дальше не выполняется, и вот собственно задача была обломить этод тред, в процессе закачки (тобиш в любой удобный момент)
← →
troits (2001-11-28 17:45) [6]>Digitman
Все круто, только немного напутано с PeekMessage ?
← →
Evgeniy_S (2001-11-28 17:50) [7]>Digitman
ну как тебе сказать, перед HTTP.GET(url) проверять смысла нет, а кокгда он отсосет страницу то сам таерминатится, а хочется прерывать процесс засоса, вот и спраивается куда в этом случае вставлять проверку на terminated?
← →
Evgeniy_S (2001-11-28 17:55) [8]ЗЫ: и просто очень интересно, почему один раз получилось и работает, а больше не хочет :(((
← →
troits (2001-11-28 17:57) [9]Может, проще использовать TerminateThread ?
Для того, чтобы stop вызвался, надо было вызвать Dispatch(Msg)
← →
Evgeniy_S (2001-11-28 18:02) [10]>troits ©
>Может, проще использовать TerminateThread ?
ну дык это уже насилие, а так делаеш просто http.disconnect + terminate и усе, а Dispatch(Msg) я не вызывал
← →
Digitman (2001-11-28 18:12) [11]>troits
ну, первым параметром еще экз-р структуры TMsg надо указать - согласен, пропустил его.
>Evgeniy_S
Понятия не имею, как у тебя все это работало вообще. Хэндл потока не тоже самое, что и хэндл окна, и сообщения в твоем варианте ты пытаешься слать, используя именно хэндл потока в качестве адресата посылаемых сообщений, что неверно да и бессмысленно.
вот этой процедурой
procedure TForm1.KillThreadButtonClick(Sender: TObject);
begin
MyThread.Suspend;
MyThread.Free;
end;
поток будет безусловно принудительно уничтожен, но ты сильно рискуешь с утечкой ресурсов, обрывая поток при выполнении им блокирующего HTTP.Get()
← →
Evgeniy_S (2001-11-28 18:23) [12]чесс слово работает (могу даже исходники показать), правда форма со веми этими делами в длл лежит, хотя сомнительно что это может влиять.
← →
Digitman (2001-11-28 18:28) [13]>Evgeniy_S
Значит, код, что ты привел, не соответствует оригиналу.
А, если соответствует, объясни тогда, что ты делаешь здесь:
procedure TForm1.Button1Click(Sender: TObject);
begin
with Thread.Create(true) do
begin
Form1._Handle := Handle; // зачем здесь Form1 ? этот объект текущий. В его поле _Handle ты записываешь хэндл только что созданного потока, а не какого-то окна
resume;
end;
end;
и здесь :
procedure TForm1.Button2Click(Sender: TObject);
begin
PostMessage(_Handle, wm_stop_thread, 2, 0); // ???????????
end;
← →
Evgeniy_S (2001-11-28 18:39) [14]>Form1._Handle := Handle; // зачем здесь Form1 ? этот объект текущий
абсолютно не нужен, просто так
>PostMessage(_Handle, wm_stop_thread, 2, 0);
ну, скажем так, раньше я думал что посылаю треду такое сообщение (теперь уже и не знаю), и причем оно посылается, хотя как я тоже не знаю
← →
Digitman (2001-11-28 18:56) [15]так, если даже так (считаешь, что посылаешь потоку сообщение), тогда :
1. Какого же черта обработчик сообщения ты объявляешь и реализуешь в форме, а не в классе потока ?? Она имеет свое окно и реагирует только на сообщения ей самой или гл.окну приложения.
2. Посылать потоку сообщение нужно вызовом PostThreadMessage(c параметром ThreadId, а не ThheadHandle), а PostMessage шлет сообщение только окну (параметр - WindowHandle, а не ThreadHandle)
3. Почему ты уверен, что сообщение посылается вызовом PostMessage() ? Где анализ результата вызова ? Он ведь - Boolean, и будет True только если сообщение реально помещено в очередь указанного (и существующего!) приемника
4. Даже если бы каким-то невероятным образом сообщение оказалось в очереди сообщений потоку, где в теле Thread.Execute ты делаешь выборку этих сообщений из очереди ? Все, что ты там делаешь - это HTTP.Get(), и ничего более. Поток сам ответственен за выборку и обработку сообщений из собственной очереди сообщений. А эта очередь инициализируется ТОЛЬКО после любого из вызовов GetMessage, PeekMessage, сделанных в коде потока.
← →
iZEN (2001-11-28 19:45) [16]/**Evgeniy_S (28.11.01 16:13):
<...>
procedure THread.execute;
begin
//делаем что то долго, циклов тут нет...
end;
<...>
*/
А как поток узнает что он терминировался из другого места?
Так вот, где-то в execute() должна происходить проверка флага на остановку. Но, так как в коде execute() нет таких проверок, то и поток будет жить, пока не выйдет из execute(), то есть пока не выполнит свою задачу доконца.
Ввыход 1: создать второй поток (Watcher) и читать данные первого работающего потока без синхронизации, если возможно, или с синхронизацией обновляемых данных в критической секции. Но в этом случае, первый поток всё равно нельзя остановить, так как в execute() нет витков-циклов и он, как я понял со слов автора и сделал вывод, не может в любое время узнать о своём терминировании.
Выход 2: опять повторюсь, без call-back-оповещений работающего потока остановить его невозможно. И дело не в WinAPI.
← →
Evgeniy_S (2001-11-29 11:53) [17]>Digitman ©
>обработчик сообщения ты объявляешь и реализуешь в форме
да нет же, он в классе треда определен
>сообщение нужно вызовом PostThreadMessage(c параметром ThreadId, а не >ThheadHandle)
и так я пробовал, всеравно
>Почему ты уверен, что сообщение посылается вызовом ...
да я говорю, что уже и не уверен, но ить работает же как то
>iZEN
>А как поток узнает что он терминировался из другого места?
вот в этом проблема и стоит, как ему об этом сказать
Ну и главный вопрос, как же тогда это реализовать? Ведь делают же как то такие штуки? Поможите плиз...
← →
paul_shmakov (2001-11-29 11:56) [18]прошу прощения, что не в тему, но лучше использовать асинхронный ввод/вывод. тем более для http.get. не знаю, позволяют ли компоненты indy использовать асинхронный io. ics, например, позволяют. их и рекомендую.
← →
Evgeniy_S (2001-11-29 12:13) [19]>paul_shmakov ©
а где лежит сей ics ?
← →
paul_shmakov (2001-12-02 02:08) [20]2 Evgeniy_S:
http://www.overbyte.be
← →
XCreator (2001-12-02 05:22) [21]Да, действительно крутой компонент. Гораздо лучше FastNet"овского.
Кстати, прошу прощения за оффтопик, никто не знает, что за исключение EJPEG? У меня прога получает картинки с нета, и при отображении появляется это исключение. В результате поисков не в хелпе, не в инете ничего не нашел.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.01.31;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.005 c