Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
3-99833
Kulagin
2001-12-21 15:34
2002.01.31
Связь Delphi с Exel


3-99844
Аль
2001-12-25 13:17
2002.01.31
Пример о DCOM


14-100054
Феликс
2001-12-10 23:12
2002.01.31
Билл Гейтс:


1-99950
dim2001
2002-01-13 20:28
2002.01.31
Запись в файл


3-99913
kopelev
2001-12-27 11:26
2002.01.31
Как программно создать индексный файл для DBF





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский