![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Прикол с TThread
Separator © (2002-11-20 13:10:00)
type
TMyThread = class(TThread);
protected
procedure Work;
procedure Execute; override;
end;
var
Form1: TForm1;
MyThread: TMyThread;
implementation
procedure TMyThread.Work;
begin
//что-нибудь делаю, главное чтоб это делалось долго
end;
procedure TMyThread.Execute;
begin
repeat
Synchronize(Work);
until Terminated
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MyThread:= TMyThread.Create(false)
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MyThread.Terminate;
MyThread.Free;
end;
end;
Если Form1.Destroy происходи когда идет работа в процедуре Work, то приложение виснет. Почему?
Если убрать Synchronize, то тогда все нормально.
Smithson (2002-11-21 15:07:00) [21]Ээээээээ, родной, не горячись. Для советского программиста слова поток и процесс - синонимы (особо для не работавшего с Novell API).
А "шаблон" - что ж, считай, что это неудачный эвфимизм слова пример.
PS. Я ни сколько не защищаю саму статью, просто предъявленные претензии, на мой взгляд, не совсем обоснованы.
Digitman (2002-11-21 14:49:00) [22]Ну ! Видел я эту статью)
С одной стороны, ему, <Кариху Николаю>, и надо бы кой-чего "подкрутить") ... Читаем эту "чушь"
>Приведем небольшой пример того, как можно создать отдельный > процесс:
(далее, по приведенному тексту примера, идет речь вовсе не о процессах , а о код.потоках)
>Пример 1. "Шаблон" для создания Thread-ов.
А вот это должно насторожить любого : Слово "шаблон" взято в кавычки ! И - правильно взято !
Нигде нет ни слова о том, в каких случаях нужен этот "шаблон" и что в нем и для чего реально делается...
Борис (2002-11-21 14:21:00) [23]Digitman
Дык, так там получается, что вся работа все-равно выполняется в основном потоке (точнее основной останавливается, ожидая когда законитя другой). имхо.
А вот по-моему и ссылочка: http://delphi.mastak.ru/articles/thread/index.html
и вот тоже ссылочка
http://delphi.mastak.ru/articles/http/index.html
вообще вначале я изучал по этой статье и начались косяки, пришлось разбираться и вникать.
Zemal (2002-11-21 14:17:00) [24]to Digitman
Спасиб! :)
Digitman (2002-11-21 14:14:00) [25]>Zemal
Терпения и успехов и тебе в постижении "непостижимого" !.........)
Zemal (2002-11-21 14:11:00) [26]to Digitman
Спасибо за толчёк в нужном направлении, спасибо за пищу для размышлений :). Ты меня озадачил. У меня действительно образовалось много дыр и некоторая каша в голове :). Полезу выкапывать детали (основную мысль я ужо ухватил :), благодаря тебе). Всё, полез в MSDN, письма оттуда ходят медленно, а транспорт вообще неходит :), посему скоро не ждите.
Digitman (2002-11-21 14:02:00) [27]
>Борис
> Я с этим примером тоже много мучился пока Digitman все неразжевал,
Видит бог - я старался)
> Может этот пример воодще из FAQ убрать (по-моему он в статьях
> лежал)
Да хрен его знает, где он "лежал" или "стоял", но, видать, и по сей день глаза мозолит все большему и большему числу программеров. Особливо - начинающих. То-то и беспокоит, ибо - "сдерут" его и понеслааааась басня Крылова про мартышек с очками) ...
>или заменить на верный, чтобы не вводить народ в
> заблуждение?
А любопытно, что есть "верный" пример ? Я таких не знаю. Просветишь может быть ?
Digitman (2002-11-21 13:52:00) [28]
>Zemal
термины "кодовый поток" и "thread" эквивалентны
см. GetWindowThreadProcessId, это даст тебе пищу для размышления и хоть какую-то определенность в понимании, кто кого "создает" и кто кем "владеет", когда речь идет не о VCL-объектах (TApplication , TForm и иже с ними), а об объектах ОС (window, process, thread e.t.c)
извини, но читать подробную лекцию на эту тему у меня нет ни времени ни желания.
Есть желание, есть книги, есть хэлп, есть MSDN - что еще надо человеку чтобы разобраться во всех этих потрохах до тонкостей ?)
Борис (2002-11-21 13:48:00) [29]Я с этим примером тоже много мучился пока Digitman все неразжевал, а потом нашел хороший pdf про TThread.
Может этот пример воодще из FAQ убрать (по-моему он в статьях лежал) или заменить на верный, чтобы не вводить народ в заблуждение?
Zemal (2002-11-21 13:40:00) [30]to Digitman
Спасибо за разъяснения :). Мы уже доплясали до объекта Application, который владеет главным окном приложения, которое в свою очередь владеет дочерними окнами и дальше объекты по иерархии :). И я незнаю такого объекта "кодовый поток" и как он может владеть чем-то? Может я ещё не достиг такого просветления сознания?!
А сообщения (Message) может принимать только объект класса TForm и это означает, что поток должен принадлежать определённой форме приложения, которая и отвечает за приём сообщений в свой стек и за диспетчирезацию и обработку их. Разьве не так?
Кстати, что ты понимаешь под термином "кодовый поток" мне очень интересно, т.к. я не до конца понимаю.
P.S. Есть конечно события и уровня Application, т.к. это тоже форма, только никто и никогда её невидел, т.к. она неимеет клиентской части и преднозначена для приёма сообщений уровня Application (Application.OnMessage) и отображения приложения на панели задач (прямоугольничек такой с надписью). Всё, дальше продолжать небуду... долго, нудно и неохото :).
Digitman (2002-11-21 13:36:00) [31]случай далеко не редкий.
пусть ты создал в среде Делфи DLL, использующую VCL, и при исполнении одного из эксп.вызовов которой (Entry1) создается экз-р TThread (Thread2)
пусть в Thread2.Execute выполняется Synchronize() для каких-то целей (разумеется, целей синхронизации неких известных методов с осн.потоком)
пусть эту DLL использует некий хост-процесс с MainThread= Thread0 , не использующий VCL и создающий доп.поток (Thread1) неким иным образом, например, прямым вызовом WinAPI CreateThread()
пусть в ходе выполнения Thread1 происходит обращение к Entry1.
при этом будет впервые вызван конструктор Thread2 := TThread.Create(...), в рез-те чего в потоке Thread1 будет создано невиз.окно для адресации ему технолог.сообщений, в т.ч. CM_EXECPROC.
поскольку CM_EXECPROC послано окну, созданному в потоке Thread1, то и выбирать/обрабатывать это сообщение должен поток Thread1. Мало того, что в теле Thread1 может быть вообще не предусмотрен цикл выборки/диспетчеризации оконных сообщений, так он еще и занимается в этот момент исполнением тела Entry1 !
вот и получается самый настоящий "конфуз")
reonid (2002-11-21 13:15:00) [32]Digitman © (21.11.02 12:44)
Чесно говоря, я не задавался вопросом -
можно ли влезть вперёд паровоза и создать
свой объект TThread до того, как дельфи создаст
ВэЦээЛьный TThread.
Я подозреваю там какую-то химию - ведь сам винапишный поток
явно создан уже когда выполняется _StartExe, а объекта
TThread для него ещё вроде как нет.
Если это так, то такой финт ушами вполне возможен.
Не знаю, не прорабатывал глубоко этот вопрос...
Если это возможно, то ты, без сомнения, прав.
Но всё равно это исключительно редкий случай.
Digitman (2002-11-21 13:15:00) [33]Здесь термин "владеет" означает как минимум одно (но - самое важное) : по-умолчанию лишь тот поток, который создал окно, имеет возможность получать сообщения, адресованные этому окну. Если не оговорены доп.требования (см. AttachThreadInput)
Digitman (2002-11-21 13:11:00) [34]
> окно, владеющее потоком
Сударь, коль скоро ты начал развивать тему "неточностей", скажу уж, что при таком раскладе мог бы и сам недопускать новых "неточностей". Причем, imho, достаточно грубых.
Окно не может владеть потоком, строго наоборот - кодовый поток, в контексте которого был создан объект-окно, владеет эти окном.
Zemal (2002-11-21 13:02:00) [35]to Digitman
Ну ты и замутил :). Мы разбераем простой пример с одним потоком и VCL-потоком. Подрозумевается, что сообщения от потока будет принимать главная форма приложения, т.е. VCL-поток, а не форма, динамически созданная потоком :). Можно ещё приплести форму из dll :). В определённых условиях всё так как описал Reonid. Эйнштейн ещё говорил, что всё в мире относительно и что является постулатом и аксиомой в одних условиях, может быть нарушено в других и даже перевёрнуто с ног на голову :). Ну ошибся Reonid в терминах, окно, владеющее потоком (Owner) назвал "специальным окном основного потока"... я думаю он просто оговорился :).
Zemal (2002-11-21 12:45:00) [36]to Smithson
Я и непредлагаю тебе её дальше вертеть :). Это я тем, кто незнает что такое потоки. Gala - хороший самоучитель и в примерах разбирает множество проблем синхроницации и обмена данными между потоками (семафоры, мьютексы, посылка сообщений, проблема дедлока и т.д.). Я и сам тоже пользуюсь API и классом потока Win32 (Thread), когда нужно написать хорошую вещь и важно быстродействие и свободные ресурсы, а если для теста, то мона быстренько и на TThread набросать, можно и Gala поюзать... это действительно на любителя :), это ты прав :).
Digitman (2002-11-21 12:44:00) [37]> reonid © (21.11.02 12:19)
> MyThread выполняет Synchronize -
> т.е. посылает (SendMessage) CM_EXECPROC
> специальному окну основного потока, останавливается
> и ждёт, пока сообщение будет обработано.
Да мало того - по кр.мере в Д5 это тоже далеко не всегда соответствует действительности. Именно - "специальному окну основногопотока".
Если самый первый объект класса TThread в свою очередь сам был создан в доп.код.потоке, то и окно будет принадлежать потоку , вызвавшему конструктор. А это значит, что осн.код.поток по-умолчанию не будет выбирать и диспетчеризовать сообщения окна, не им созданного. Иными словами, WaitFor, вызванный в дан.случае в осн.код.потоке даст совершенно неожиданный и неверный результат.
Zemal (2002-11-21 12:36:00) [38]to Reonid
Ловко! Молодец! Ты хороший гросмейстер! :) Однозначно дедлок потока TMyThread с VCL-потоком :). Хорошо ты разжевал... с подробностями и смакуя :). Молодец!
Smithson (2002-11-21 12:34:00) [39]>> Zemal
Вертел я как-то эту галу, вертел - и вернулся к TThread + немного API. Так что оно на любителя.
Zemal (2002-11-21 12:32:00) [40]to Smithson
Да чего мы тут разжевали-то! Разьве этого хватит? Мы только ещё раз подтолкнули к литературе и FAQ, а чего надо было искать Separator и без этого знал... мог бы и без нас найти ответ на эту проблему. Просто лень забивает :(, а это плохо... очень плохо... ленивый программист хуже футболиста (из анекдота: Жили-были дед и бабка и было у них три сына - два умных, а третий футболист).
to Separator
Больше читать надо... вот к чему я веду. По другому только людей на форуме раздражать будешь и это всё чего сможешь добиться. Разьве мало литературы? Или ты выше этого? А вообще-то, зачем тебе она впёрлась, если на форуме за тебя весь код напишут... логика железная.
to All
Советую всем кто плохо знает потоки изучить одну библиотечку, там очень хороший и доступный самоучитель и класная справка (всё на русском). Вот ссылка: http://gurin.tomsknet.ru/gala.html
Скачивайте оттуда библиотеку Gala и пользуйтесь наздоровье, там представлены решения всех возможных проблем с потоками, а при более глубоком рассмотрении библиотеки вы сможете создавать потоки непосредственно виндовые (и забудете про класс TThread напрочь :) ).