Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.12.02;
Скачать: [xml.tar.bz2];

Вниз

Прикол с TThread   Найти похожие ветки 

 
Separator   (2002-11-20 13:10) [0]

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, то тогда все нормально.


 
Skier   (2002-11-20 13:13) [1]

>Separator
Form1.Release ?


 
Separator   (2002-11-20 13:17) [2]


> Form1.Release
Это что такое?


 
NailS   (2002-11-20 13:18) [3]

>Synchronize(Work);

И процедура Work выполняется в главном потоке. ;)
А почему виснет при выходе пройдись пошагово, посмотри что происходит.


 
Какой ужас   (2002-11-20 13:20) [4]

Процедуры, которые вызываются через Synchronize,
на самом деле вызываются из основного потока.
При этом твой поток останавливается и ждёт, когда
основной выполнит эту процедуру.
(А основной поток при этом может ждать, когда окончится твой поток - так он и делает при разрушении объекта TMyThread)

Надо в Synchronize выносить только то, что не рекомендуется делать пользовательском потоке - в основном, это
обновление интерфейса. Это должны быть короткие процедуры.


 
Separator   (2002-11-20 13:21) [5]


> NailS © (20.11.02 13:18)
проходил и не раз, ничего не происходит, просто виснет


 
Слесарь Матерящийся   (2002-11-20 13:23) [6]

>просто виснет

Вполне логично.


 
Ice Scream   (2002-11-20 13:24) [7]

destructor TMyThread.Destroy;
begin
if Suspended then Resume else Suspend;
Terminate;
end;


 
asmith   (2002-11-20 13:36) [8]

Проблема в том, что вызов MyThread.Terminate не останавливает поток, а только сигнализирует ему, что нужно остановиться, устанавливая свойство Terminated в True. Поэтому для уничтожения потока вызовом MyThread.Free нужно дождаться завершения потока. Проще всего этого добиться установкой FreeOnTerminate в True при создании и все.


 
Digitman   (2002-11-20 13:38) [9]

Руки бы поотрывать тому, кто этот пример "запустил" в FAQ как программный шаблон, которому неукоснительно надо следовать при работе с TThread.
А заодно и головы тем, кто с завидной регулярностью совершенно бездумно, не вникая в суть и не читая документацмм, "сдирает" этот пример и после этого заваливает форум вопросами про якобы "приколы".


 
Separator   (2002-11-21 08:00) [10]


> Digitman © (20.11.02 13:38)
Вполне согласен, просто я хотел поинтересоваться почему так происходит. Я уже давно решил эту проблему. Всем спасибо


 
Digitman   (2002-11-21 08:32) [11]

>Separator

Ну так ты выяснил - почему ?


 
Separator   (2002-11-21 08:41) [12]

ДА


 
Smithson   (2002-11-21 09:01) [13]

Ну и?


 
MetalFan   (2002-11-21 11:15) [14]

to Separator
ага, мне тож интересно)))
где ошибка то?


 
Fantasist   (2002-11-21 11:18) [15]


> Smithson © (21.11.02 09:01)
> Ну и?


А что тут не понятного? Вызывается Work в основном потоке - тыкаем закрыть форму - сообщение об этом помещается в очередь сообщений и висит там, пока Work не закончит работать. После этого - главное окно сразу же закрывается и по видимому закрывается тот механизм, что обеспечивает работу Synchronize (не помню точно как у них - кажись через сообщения и какие-то глобальные переменные). Сам поток не прекращает выполнение(по видимому он успевает пройти через "until Terminated" до того, как главный поток изменяет это значение) и доходит до Synchronize(Work) после чего начинает ждать пока основной поток вызовет и отработает этот Work, чего тот никогда не делает.


 
Fantasist   (2002-11-21 11:19) [16]

Вообще мне VCL-евская синхронизация не очень нравиться.


 
MyEN   (2002-11-21 11:26) [17]

дэдлок? ;))


 
Fantasist   (2002-11-21 11:37) [18]


> дэдлок? ;))


Не, deadlock - это когда два(или более) объекта ждут друг друга. В этом же случае, поток просто ждет, того, чего уже нет.


 
Zemal   (2002-11-21 11:59) [19]

Даааа... ну и дела... я в задумках... Separator, ты отдельно живёшь от своего мозга? Зачем выносить вопрос на форум, если ты уже решил проблему? Возьми книгу, почитай. Или в FAQ поищи. А когда наберётся в головёнке большая часть информации - тогда и проясниться всё, тогда и всё сразу станет понятно. И нечего отвлекать людей по глупостям. Это же элементарная теория потоков!

>>Если Form1.Destroy происходи когда идет работа в процедуре
>>Work, то приложение виснет. Почему?

А почему ты неможешь работать и идти домой одновременно? Посмотри ещё дополнительно информацию про сообщения, наверняка незнаешь как происходит закрытие приложения и что такое стек сообщений главного окна приложения.

>> procedure TMyThread.Work;
>> begin
>> //что-нибудь делаю, главное чтоб это делалось долго
>> end;

Потоки и должны выполнять это самое "долго". Нафига тебе понадобилось грузить VCL поток? Единственное, что у тебя будет выполняться в твоём потоке, так это только то что описано в Execute, остальные вызовы будут в VCL потоке выполняться. И естественно, когда VCL поток загружен работой, то он и будет производить впечатление зависшего приложения (на самом деле оно не висит, а лишь поуши в работе).
И что вам всем лень почитать? Выносите на форум и что надо и что ненадо... лишь бы было. У тебя же были зацепочки твоей проблемы, мог бы взять и раскрутить (поискать FAQ, полистать книгу). Другое дело, когда незнаешь почему и не знаешь что и где искать - тогда люди помогут, а по пустякам людей беспокоить нестоит - боком может выйти.


 
Zemal   (2002-11-21 12:07) [20]

Кстати, этот пример (который тут разбирается) шаблон из FAQ что-ли? Даааа... бывают и придурки, которые FAQ пишут! Этож надо додуматься! Создавать поток для многократного запуска процедуры в VCL потоке! Такой дури я ещё в FAQ не встречал! Separator, поделись где ты откапал такую пургу?


 
Smithson   (2002-11-21 12:09) [21]

//Fantasist ©
Не сочти за наезд, но здесь форум, то бишь школа. Человек задал вопрос, ему накидали вариантов, он что-то нашел и решил задачу. Вот я и прошу выложить решение, что бы потом можно было сюда отсылать следующего с таким же вопросом. Правда, ты и Zemal ответ разжевали, так что мое желание выполнено.

//Zemal
Sorry за offtop


 
reonid   (2002-11-21 12:19) [22]

Fantasist © (21.11.02 11:18)

Типичнейший, ИМХО, дедлок:

MyThread выполняет Synchronize -
т.е. посылает (SendMessage) CM_EXECPROC
специальному окну основного потока, останавливается
и ждёт, пока сообщение будет обработано.

А основной поток в это время занят обработкой
WM_CLOSE, пришедшее для основной формы
(в результате вызывается OnClose), и пока
он его не обработает, он не обработает, он не
займётся CM_EXECPROC.

Но в процессе выполнения OnClose он вызывает
деструктор TMyThread - который, в свою очередь,
вызывает WaitFor - теперь основной поток останавливается
и ждёт, когда закончится MyThread, который ждёт, когда основной поток обработает его CM_EXECPROC.

Всё. Мат в два хода.


 
Zemal   (2002-11-21 12:32) [23]

to Smithson
Да чего мы тут разжевали-то! Разьве этого хватит? Мы только ещё раз подтолкнули к литературе и FAQ, а чего надо было искать Separator и без этого знал... мог бы и без нас найти ответ на эту проблему. Просто лень забивает :(, а это плохо... очень плохо... ленивый программист хуже футболиста (из анекдота: Жили-были дед и бабка и было у них три сына - два умных, а третий футболист).

to Separator
Больше читать надо... вот к чему я веду. По другому только людей на форуме раздражать будешь и это всё чего сможешь добиться. Разьве мало литературы? Или ты выше этого? А вообще-то, зачем тебе она впёрлась, если на форуме за тебя весь код напишут... логика железная.

to All
Советую всем кто плохо знает потоки изучить одну библиотечку, там очень хороший и доступный самоучитель и класная справка (всё на русском). Вот ссылка: http://gurin.tomsknet.ru/gala.html
Скачивайте оттуда библиотеку Gala и пользуйтесь наздоровье, там представлены решения всех возможных проблем с потоками, а при более глубоком рассмотрении библиотеки вы сможете создавать потоки непосредственно виндовые (и забудете про класс TThread напрочь :) ).


 
Smithson   (2002-11-21 12:34) [24]

>> Zemal
Вертел я как-то эту галу, вертел - и вернулся к TThread + немного API. Так что оно на любителя.


 
Zemal   (2002-11-21 12:36) [25]

to Reonid
Ловко! Молодец! Ты хороший гросмейстер! :) Однозначно дедлок потока TMyThread с VCL-потоком :). Хорошо ты разжевал... с подробностями и смакуя :). Молодец!


 
Digitman   (2002-11-21 12:44) [26]

> reonid © (21.11.02 12:19)

> MyThread выполняет Synchronize -
> т.е. посылает (SendMessage) CM_EXECPROC
> специальному окну основного потока, останавливается
> и ждёт, пока сообщение будет обработано.

Да мало того - по кр.мере в Д5 это тоже далеко не всегда соответствует действительности. Именно - "специальному окну основного потока".

Если самый первый объект класса TThread в свою очередь сам был создан в доп.код.потоке, то и окно будет принадлежать потоку , вызвавшему конструктор. А это значит, что осн.код.поток по-умолчанию не будет выбирать и диспетчеризовать сообщения окна, не им созданного. Иными словами, WaitFor, вызванный в дан.случае в осн.код.потоке даст совершенно неожиданный и неверный результат.


 
Zemal   (2002-11-21 12:45) [27]

to Smithson
Я и непредлагаю тебе её дальше вертеть :). Это я тем, кто незнает что такое потоки. Gala - хороший самоучитель и в примерах разбирает множество проблем синхроницации и обмена данными между потоками (семафоры, мьютексы, посылка сообщений, проблема дедлока и т.д.). Я и сам тоже пользуюсь API и классом потока Win32 (Thread), когда нужно написать хорошую вещь и важно быстродействие и свободные ресурсы, а если для теста, то мона быстренько и на TThread набросать, можно и Gala поюзать... это действительно на любителя :), это ты прав :).


 
Zemal   (2002-11-21 13:02) [28]

to Digitman
Ну ты и замутил :). Мы разбераем простой пример с одним потоком и VCL-потоком. Подрозумевается, что сообщения от потока будет принимать главная форма приложения, т.е. VCL-поток, а не форма, динамически созданная потоком :). Можно ещё приплести форму из dll :). В определённых условиях всё так как описал Reonid. Эйнштейн ещё говорил, что всё в мире относительно и что является постулатом и аксиомой в одних условиях, может быть нарушено в других и даже перевёрнуто с ног на голову :). Ну ошибся Reonid в терминах, окно, владеющее потоком (Owner) назвал "специальным окном основного потока"... я думаю он просто оговорился :).


 
Digitman   (2002-11-21 13:11) [29]


> окно, владеющее потоком


Сударь, коль скоро ты начал развивать тему "неточностей", скажу уж, что при таком раскладе мог бы и сам недопускать новых "неточностей". Причем, imho, достаточно грубых.

Окно не может владеть потоком, строго наоборот - кодовый поток, в контексте которого был создан объект-окно, владеет эти окном.


 
Digitman   (2002-11-21 13:15) [30]

Здесь термин "владеет" означает как минимум одно (но - самое важное) : по-умолчанию лишь тот поток, который создал окно, имеет возможность получать сообщения, адресованные этому окну. Если не оговорены доп.требования (см. AttachThreadInput)


 
reonid   (2002-11-21 13:15) [31]

Digitman © (21.11.02 12:44)

Чесно говоря, я не задавался вопросом -
можно ли влезть вперёд паровоза и создать
свой объект TThread до того, как дельфи создаст
ВэЦээЛьный TThread.

Я подозреваю там какую-то химию - ведь сам винапишный поток
явно создан уже когда выполняется _StartExe, а объекта
TThread для него ещё вроде как нет.
Если это так, то такой финт ушами вполне возможен.
Не знаю, не прорабатывал глубоко этот вопрос...

Если это возможно, то ты, без сомнения, прав.
Но всё равно это исключительно редкий случай.


 
Digitman   (2002-11-21 13:36) [32]

случай далеко не редкий.

пусть ты создал в среде Делфи 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 !

вот и получается самый настоящий "конфуз")


 
Zemal   (2002-11-21 13:40) [33]

to Digitman
Спасибо за разъяснения :). Мы уже доплясали до объекта Application, который владеет главным окном приложения, которое в свою очередь владеет дочерними окнами и дальше объекты по иерархии :). И я незнаю такого объекта "кодовый поток" и как он может владеть чем-то? Может я ещё не достиг такого просветления сознания?!
А сообщения (Message) может принимать только объект класса TForm и это означает, что поток должен принадлежать определённой форме приложения, которая и отвечает за приём сообщений в свой стек и за диспетчирезацию и обработку их. Разьве не так?
Кстати, что ты понимаешь под термином "кодовый поток" мне очень интересно, т.к. я не до конца понимаю.
P.S. Есть конечно события и уровня Application, т.к. это тоже форма, только никто и никогда её невидел, т.к. она неимеет клиентской части и преднозначена для приёма сообщений уровня Application (Application.OnMessage) и отображения приложения на панели задач (прямоугольничек такой с надписью). Всё, дальше продолжать небуду... долго, нудно и неохото :).


 
Борис   (2002-11-21 13:48) [34]

Я с этим примером тоже много мучился пока Digitman все неразжевал, а потом нашел хороший pdf про TThread.

Может этот пример воодще из FAQ убрать (по-моему он в статьях лежал) или заменить на верный, чтобы не вводить народ в заблуждение?


 
Digitman   (2002-11-21 13:52) [35]


>Zemal

термины "кодовый поток" и "thread" эквивалентны

см. GetWindowThreadProcessId, это даст тебе пищу для размышления и хоть какую-то определенность в понимании, кто кого "создает" и кто кем "владеет", когда речь идет не о VCL-объектах (TApplication , TForm и иже с ними), а об объектах ОС (window, process, thread e.t.c)

извини, но читать подробную лекцию на эту тему у меня нет ни времени ни желания.
Есть желание, есть книги, есть хэлп, есть MSDN - что еще надо человеку чтобы разобраться во всех этих потрохах до тонкостей ?)


 
Digitman   (2002-11-21 14:02) [36]


>Борис

> Я с этим примером тоже много мучился пока Digitman все неразжевал,

Видит бог - я старался)

> Может этот пример воодще из FAQ убрать (по-моему он в статьях
> лежал)

Да хрен его знает, где он "лежал" или "стоял", но, видать, и по сей день глаза мозолит все большему и большему числу программеров. Особливо - начинающих. То-то и беспокоит, ибо - "сдерут" его и понеслааааась басня Крылова про мартышек с очками) ...


>или заменить на верный, чтобы не вводить народ в
> заблуждение?

А любопытно, что есть "верный" пример ? Я таких не знаю. Просветишь может быть ?


 
Zemal   (2002-11-21 14:11) [37]

to Digitman
Спасибо за толчёк в нужном направлении, спасибо за пищу для размышлений :). Ты меня озадачил. У меня действительно образовалось много дыр и некоторая каша в голове :). Полезу выкапывать детали (основную мысль я ужо ухватил :), благодаря тебе). Всё, полез в MSDN, письма оттуда ходят медленно, а транспорт вообще неходит :), посему скоро не ждите.


 
Digitman   (2002-11-21 14:14) [38]

>Zemal

Терпения и успехов и тебе в постижении "непостижимого" !.........)


 
Zemal   (2002-11-21 14:17) [39]

to Digitman
Спасиб! :)


 
Борис   (2002-11-21 14:21) [40]

Digitman

Дык, так там получается, что вся работа все-равно выполняется в основном потоке (точнее основной останавливается, ожидая когда законитя другой). имхо.

А вот по-моему и ссылочка: http://delphi.mastak.ru/articles/thread/index.html

и вот тоже ссылочка
http://delphi.mastak.ru/articles/http/index.html

вообще вначале я изучал по этой статье и начались косяки, пришлось разбираться и вникать.


 
Digitman   (2002-11-21 14:49) [41]

Ну ! Видел я эту статью)

С одной стороны, ему, <Кариху Николаю>, и надо бы кой-чего "подкрутить") ... Читаем эту "чушь"


>Приведем небольшой пример того, как можно создать отдельный > процесс:

(далее, по приведенному тексту примера, идет речь вовсе не о процессах , а о код.потоках)


>Пример 1. "Шаблон" для создания Thread-ов.

А вот это должно насторожить любого : Слово "шаблон" взято в кавычки ! И - правильно взято !

Нигде нет ни слова о том, в каких случаях нужен этот "шаблон" и что в нем и для чего реально делается...


 
Smithson   (2002-11-21 15:07) [42]

Ээээээээ, родной, не горячись. Для советского программиста слова поток и процесс - синонимы (особо для не работавшего с Novell API).
А "шаблон" - что ж, считай, что это неудачный эвфимизм слова пример.
PS. Я ни сколько не защищаю саму статью, просто предъявленные претензии, на мой взгляд, не совсем обоснованы.


 
MBo   (2002-11-21 15:09) [43]

>Smithson
Это почему еще синонимы??????


 
Digitman   (2002-11-21 15:11) [44]

>Smithson

Давай уж без панибратства, "родной")


> Для советского программиста слова поток и процесс - синонимы


Чушь. Полная.


> особо для не работавшего с Novell API


Мы тут рассуждаем как бы о Win32


 
Smithson   (2002-11-21 15:26) [45]

>MBO
потому как все мы вышли из IBM mainframe, где понятия thread и process имеют чисто косметические различия.

>Digitman
Давай без панибратства. Я не знаю, о чем вы тут рассуждаете, я говорю о привычке мыслить и умении не цеплятся к словам. Извини, если это не описано в доке на Win32.


 
Digitman   (2002-11-21 15:36) [46]


> Smithson


Ну и мысли себе на здоровье)
Но если ты излагаешь свою мысль напоказ, в дан.случае - в публичной статье как рекомендацию, будь уж любезен выверить и "вылизать" каждое слово и каждый термин. Ибо в результате мы имеем ту то, что имеем. А именно - регулярные "приколы" со ссылкой на бездумно "содранный" код и "проглоченную без хлеба" терминологию. Приколы эти - то ли в "процессах", то ли в "тредах", то ли еще хрен знает где ... И при этом таки речь как бы идет все же о Win32 в 1-ю очередь... Откуда , собссно, и "растут ноги"


 
Игорь Шевченко   (2002-11-21 15:42) [47]

Smithson © (21.11.02 15:26)


> потому как все мы вышли из IBM mainframe, где понятия thread
> и process имеют чисто косметические различия.


Ну-ка, ну-ка, поподробнее на эту тему, плз, уважаемый ?... Особенно про понятие Thread у IBM MainFrame...


 
Smithson   (2002-11-21 15:42) [48]

Good ^-))

Первое китайское правило спора - "прежде чем начинать дисскусию, договорись о терминах". Придумано не то в 3, не то во 2 тысячелетии до нашей эры. До сих пор актуально.


 
Digitman   (2002-11-21 15:48) [49]

>Smithson

Не забывай, что здесь, в delphi.mastak.ru, осн.темы дискуссий и споров как правило "вертятся" вокруг строго определенной платформы - Win32. Если - иная платформа, это оговаривается особо.

В Win32 же правила установлены не тобой и не мной и не китайцами.
Хочешь быть причастным к "таинствам" платформы - принимай правила и термины. И не занимайся никчемной философией. Это - для другого места, для "Потрепаться"


 
Digitman   (2002-11-21 16:04) [50]

>Smithson

Возьми в руки ноты с "Шуткой" и, прежде чем рассуждать о красоте или безобразии ее гармонии, иди и договаривайся с Людвигом Иванычем Бетховеновым о том, в каком строе следует интерпретировать увиденный на нижней линейке стана значек : как "до" такой-то октавы европейского равномерно темперированного строя или хрен знает чего в хрен знает каком папуасском строе)


 
Digitman   (2002-11-21 16:09) [51]

>Smithson

Однако ты не идешь к композитору, а садишься за инструмент и с уверенностью берешь ноту. Вопрос тебе - почему ? А не поспорить ли с кем начсет "стандарта" за неимением под рукой его "изобретателя" и "последователя" ?)


 
Fantasist   (2002-11-22 00:35) [52]


> Но в процессе выполнения OnClose он вызывает
> деструктор TMyThread - который, в свою очередь,
> вызывает WaitFor - теперь основной поток останавливается
>
>


Даже так. Не думал что там деструктор такой умный - думал просто грохает объект и все дела, а поток естессвенно оставляет жить, ну а окно которое должно обработать сообщение CM_EXECPROC естесственно тоже грохается и поток повисает на WaitForSingleObject. Внутрь лень было смотреть. Оказывается все не совсем так.


 
Fantasist   (2002-11-22 00:50) [53]


> А вот по-моему и ссылочка: http://delphi.mastak.ru/articles/thread/index.html


Да, это статьей назвать тяжело. Фактически пересказ хелпа. Ничего не объясняется


 
Fantasist   (2002-11-22 02:20) [54]


> пусть в Thread2.Execute выполняется Synchronize() для каких-то
> целей (разумеется, целей синхронизации неких известных методов
> с осн.потоком)


А интересно, как у тебя в длл работает Synchronize? Он ведь использует SyncList - глобальную переменную, которая для длл совсем не та же самая, что для главного приложения.


 
Digitman   (2002-11-22 08:15) [55]

Я описываю ситуацию именно для Д5. Никаких SyncList"ов в Д5 Classes.pas нет.

constructor TThread.Create(CreateSuspended: Boolean);
var
Flags: DWORD;
begin
inherited Create;
AddThread; // здесь окно и создается, если это 1-й экземпляр
FSuspended := CreateSuspended;
Flags := 0;
if CreateSuspended then Flags := CREATE_SUSPENDED;
FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
end;


 
NailS   (2002-11-22 11:39) [56]

А в шестой Дельфе реализация метода Syncronize и WaitFor претерпела значительные изменения, и теперь код, работавший под пятеркой может доставить несколько бодрых минут в шестой


 
Digitman   (2002-11-22 12:25) [57]

>NailS
Д6 у меня нет под рукой.

Попробуй сымитировать приведенную мной ситуацию в Д6:

- построй хост-приложение с "Build With Run-Time Packages" = False;
- построй TestDLL с "Build With Run-Time Packages" = True;

- в осн.потоке хост-процесса создай какую-нибудь форму (видимую) с единственным компонентом TestLabel: TLabel; пусть текст метки изначально = "";

- стартуй в хост-процессе доп.код.поток непосредственным WinAPI-вызовом CreateThread() (или BeginThread - как будет удобней);

- в теле поточной ф-ции загрузи TestDLL и вызови из нее нее ф-цию TestFunc(), передав ей параметром TestLabel;

- в теле TestDLL.TestFunc() создай VCL-поток TestThread: TTestThread;
- в теле TTestThread.DoWork() выполни TestLabel.Caption := "Что-то там";
- в теле TTestThread.Execute() выполни Syncronize(DoWork);

если метка TestLabel в результате обновится, значит, проблема снята, иначе - все как и прежде


 
reonid   (2002-11-22 13:14) [58]

Digitman © (22.11.02 12:25)
>- стартуй в хост-процессе доп.код.поток непосредственным WinAPI->вызовом CreateThread() (или BeginThread - как будет удобней);

Вскрытие показало, что в Д5 это это не обязательно. Сойдёт и TThread. Неважно, как создан поток в ЕХЕ, в ДЛЛ идёт свой отсчёт.

А если уж использовать CreateThread - то можно обойтись и без
ДЛЛ.


 
Digitman   (2002-11-22 13:42) [59]


> reonid © (22.11.02 13:14)


> Неважно, как создан поток в ЕХЕ, в ДЛЛ идёт свой отсчёт.


Важно. Если и хост-процесс и DLL-модуль собраны с "Build With Run-Time Packages" = True, то они будут использовать один и тот же экземпляр vcl50.bpl, и блок переменных

var
ThreadLock: TRTLCriticalSection;
ThreadWindow: HWND;
ThreadCount: Integer;

у них будет общий.

Это означает, что, если хост-процесс в основном потоке первым вызовет TTestThread.Create(), то и ThreadWindow будет создано в осн.потоке, что противоречит условиям проблемы.



> если уж использовать CreateThread - то можно обойтись и без ДЛЛ.


Не спорю, можно и обойтись. Но DLL я упомянул для имитации достаточно распространенных "боевых" условий :

- хост-приложение - "чужое", заранее неизвестно, в какой среде оно собрано;

- DLL вполне может быть неким плагином для хост-приложения;
в теле вызова одной из ф-ций плагина необходимо, скажем, создать экз-р формы, стартовать длительные вычисления с использованием TThread, а прогресс-статус вычислений отображать с пом. Synchronize() в этой форме, после завершения/прерывания форму уничтожить и вернуть управление вызывающему хост-процессу


 
NailS   (2002-11-22 14:50) [60]


> Digitman © (22.11.02 12:25)

Synchronize не работает. ;(


 
Digitman   (2002-11-22 14:52) [61]


> NailS


Так я и думал)
С чем и поздравляю "от души"))))



 
Fantasist   (2002-11-22 21:45) [62]


> Я описываю ситуацию именно для Д5. Никаких SyncList"ов в
> Д5 Classes.pas нет.


Нормально! Вот D6 код:



type
TSyncProc = record
Thread: TThread;
Signal: THandle;
end;

.....
procedure TThread.Synchronize(Method: TThreadMethod);
var
SyncProc: TSyncProc;
begin
{$IFDEF MSWINDOWS}
SyncProc.Signal := CreateEvent(nil, True, False, nil);
try
{$ENDIF}
{$IFDEF LINUX}
FillChar(SyncProc, SizeOf(SyncProc), 0); // This also initializes the cond_var
{$ENDIF}
EnterCriticalSection(ThreadLock);
try
FSynchronizeException := nil;
FMethod := Method;
SyncProc.Thread := Self;
SyncList.Add(@SyncProc);
ProcPosted := True;
if Assigned(WakeMainThread) then
WakeMainThread(Self);
{$IFDEF MSWINDOWS}
LeaveCriticalSection(ThreadLock);
try
WaitForSingleObject(SyncProc.Signal, INFINITE);
finally
EnterCriticalSection(ThreadLock);
end;
{$ENDIF}
{$IFDEF LINUX}
pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
finally
LeaveCriticalSection(ThreadLock);
end;
{$IFDEF MSWINDOWS}
finally
CloseHandle(SyncProc.Signal);
end;
{$ENDIF}
if Assigned(FSynchronizeException) then raise FSynchronizeException;
end;


Обратите внимание на SyncList. В этот лист заносятся методы которые надо выполнить синхронно. Там же в сlasses есть функция ChekSynchronize, которая выполняет все методы из этого листа и активизирует соответствующии ивенты(которые TSyncProc.Signal). Эта функция вызывается Application.WndProc на сообщение WM_NULL, и в Application.Idle. WM_NULL поститься при помощи "события" WakeMainThread из Synchronize - оно инициализируется соответсвующей функцией TApplication.WakeMainThread.



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

Форум: "Основная";
Текущий архив: 2002.12.02;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.64 MB
Время: 0.01 c
1-4313
Whippi
2002-11-21 15:10
2002.12.02
Как переименовать?


14-4576
Николай Быков
2002-11-09 10:53
2002.12.02
Почему по выходным жизнь на сайте замирает?


1-4395
al-bee
2002-11-22 12:57
2002.12.02
Впорос по сепараторам


6-4530
Artemkin
2002-09-26 18:15
2002.12.02
Как прочитать файл с другого компа в лок. сети?


1-4441
Южанин
2002-11-20 09:38
2002.12.02
Кто скажет





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский