Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизВыполнение процедуры в потоке Найти похожие ветки
← →
AbrosimovA (2003-06-06 16:54) [0]Я создаю отдельный поток для выполнения процедуры длительных расчетов. Пишу так:
procedure TCountThread.Execute;
begin
{ Place thread code here }
FreeOnTerminate:=true;
Synchronize(Count);
end;
procedure TCountThread.Count;
begin
MainForm.Sum;//Процедура из основной формы
end;
В этом случае процедура Sum выполняется в созданном потоке или всё-таки в потоке приложения?
← →
Skier (2003-06-06 16:59) [1]методы классов VCL выполняются в контексте основного потока приложения
← →
Suntechnic (2003-06-07 01:44) [2]>Skier ©
методы классов VCL выполняются в контексте основного потока приложения
Любые методы любых классов выполняются в контексте тех потоков, в которых они вызываются, естественно, если не происходит диспетчеризация вызовов, как например в случае сSynchronize
>AbrosimovA (06.06.03 16:54)
В этом случае процедура Sum выполняется в созданном потоке или всё-таки в потоке приложения?
В принципе в основном потоке. Метод вызванный черезSynchronize
будет вызван в контексте того потока, который первым породил объект TThread, но так как первый раз породить объект TThread можно только в контексте основного потока (конечно один объект TThread может в методе Execute создать другой TThread, но он уже не будет первым), то получается что вызов всегда происходит в основном потоке приложения.
← →
Armen (2003-06-08 15:13) [3]>Suntechnic
Все правильно + Synchronize Инициализирует TCriticalSection и блокирует остальные нити от Read, Write memory Main Thread-а.
Так что если хочешь настоящего Thread-a, убери MainForm.Sum в отдельную процедуру (не метод класса), и вызовы Syncronize(Method) делай только по необходимости.
← →
AbrosimovA (2003-06-09 07:58) [4]Всем спасибо.
← →
Digitman (2003-06-09 08:53) [5]
> Suntechnic
> но так как первый раз породить объект TThread можно только
> в контексте основного потока
не факт.
конструктор TThread может быть вызван в контексте эксп.ф-ции DLL, которую, в свою очередь, может вызвать доп.код.поток хост-процесса, не использующего VCL и создавшего средствами WinAPI
т.е. если поточная ф-ция в хост-процессе была создана с пом. CreateThread() и в теле ее была вызвана эксп.ф-ция, использующая класс TThread (LoadLibrary, GetProcAddr и т.д.), то окно метод Synchronize будет синхронизировать исполнение метода-параметра с тем потоком, который впервые вызвал библ.ф-цию, создавшую самый первый экз-р TThread
← →
Suntechnic (2003-06-09 15:22) [6]>Digitman ©
конструктор TThread может быть вызван в контексте эксп.ф-ции DLL, которую, в свою очередь, может вызвать доп.код.поток хост-процесса, не использующего VCL и создавшего средствами WinAPI
Именно это я и имел ввиду когда говорил в "в принципе". Безусловно те случаи, что Вы описали, имеют место быть, но если вести речь о разработках только на VCL, то шансы получить такую ситуацию ничтожно малы.
← →
HolyGlory (2003-06-09 16:25) [7]
> >Suntechnic
> Все правильно + Synchronize Инициализирует TCriticalSection
> и блокирует остальные нити от Read, Write memory Main Thread-а.
Ды ты что? Как же это так? Посмотри исходник TApplication.Run() - всё, что запущенно через TThread.synchronize(...) выполняется процедурой (точнее ф-цией) CheckSynchronize, которвя (в основном) постоянно вызывается методом Application.Run().
Попробуй запустить сл. поток:
procedure TMyThread.SNC();
Begin
Label1.Caption:=Variant(GetTickcount);
End;
procedure TMyThread.Execute();
Begin
while true do Syncrhonize(self.SNC);
end;
А затем загрузи чем-нить основной поток - поток TMyThread исполнятся не будет!
>
> Так что если хочешь настоящего Thread-a, убери MainForm.Sum
> в отдельную процедуру (не метод класса), и вызовы Syncronize(Method)
> делай только по необходимости.
А почему не метод класса? Чем метод класса отличается от процедуры? Это та же самая процедура, которой передается указатель на поля и др. инф.
> т.е. если поточная ф-ция в хост-процессе была создана с
> пом. CreateThread() и в теле ее была вызвана эксп.ф-ция,
> использующая класс TThread (LoadLibrary, GetProcAddr и т.д.),
> то окно метод Synchronize будет синхронизировать исполнение
> метода-параметра с тем потоком, который впервые вызвал библ.ф-цию,
> создавшую самый первый экз-р TThread
В этом случае Synchronize работать не будет вообще (либо Access Violation либо просто нафиг повиснет). Смотри реализацию Synchronize и TApplication. Вот цитата из helpa :
Delphi syntax:
function CheckSynchronize(Timeout: Integer = 0): Boolean;
C++ syntax:
extern PACKAGE bool __fastcall CheckSynchronize(int Timeout = 0);
Description
It is not necessary to call CheckSynchronize in a GUI application. The call to CheckSynchronize is made automatically by the application object. In a non-GUI application, you must call CheckSynchronize if you use the Synchronize method of TThread. To do this, set the WakeMainThread variable to a procedure that calls CheckSynchronize.
CheckSynchronize allows background threads to synchronize their execution with the main thread, so that it is safe to make method calls in the background thread.
CheckSynchronize returns true if a method was synchronized, false if it does nothing.
Сам удивился. (Это только Delphi 7 - реализацию в других версиях не проверял).
← →
Digitman (2003-06-09 16:32) [8]
> шансы получить такую ситуацию ничтожно малы
опять же - не факт.
скажем, хост-приложение, грузящее и использующее DLL-плагин, разрабатывает С-шник в MSVC (загрузка и использование входов плагина вполне может происходить в доп.код.потоке), а сам DLL-плагин разрабатывается в Делфи с использованием VCL и TThread конкретно.
← →
Suntechnic (2003-06-09 18:24) [9]>Digitman © (09.06.03 16:32)
Ещё раз повторяю
"но если вести речь о разработках только на VCL, то шансы получить такую ситуацию ничтожно малы."
Ситуация описанная в (09.06.03 16:32) не удовлетворяет тем условиям, которые я указывал в своём посте.
← →
kull (2003-06-09 18:46) [10]
> Digitman © (09.06.03 16:32)
А как же Хелп?
там написано: Executes Method within the main VCL thread.
← →
Suntechnic (2003-06-09 18:50) [11]>HolyGlory
> т.е. если поточная ф-ция в хост-процессе была создана с
> пом. CreateThread() и в теле ее была вызвана эксп.ф-ция,
> использующая класс TThread (LoadLibrary, GetProcAddr и т.д.),
> то окно метод Synchronize будет синхронизировать исполнение
> метода-параметра с тем потоком, который впервые вызвал библ.ф-цию,
> создавшую самый первый экз-р TThread
В этом случае Synchronize работать не будет вообще (либо Access Violation либо просто нафиг повиснет). Смотри реализацию Synchronize и TApplication. Вот цитата из helpa :
Это почему не будет? И с какой стати Access Violation или отвисание? Точнее проблемы то как раз быть могут ввиду того что вызовы Synchronize ничего не синхронизируют с основным потоком.
Что касаетсяCheckSynchronize
то у меня такого зверя вообще в Delphi 5 не наблюдается. Так что вполне возможно что мы ведём речь каждый о своей версии VCL.
← →
HolyGlory (2003-06-09 18:53) [12]2Digitman и Suntechnic :
О чем спор?
← →
Suntechnic (2003-06-09 18:58) [13]>HolyGlory (09.06.03 18:53)
Да не спор это вовсе. Мы говорим об одном и том же, только каждый своими словами :)
← →
HolyGlory (2003-06-09 19:02) [14]
> Что касается CheckSynchronize то у меня такого зверя вообще
> в Delphi 5 не наблюдается. Так что вполне возможно что мы
> ведём речь каждый о своей версии VCL.
Да, действителбно. Я вот тоже когда увидел - удивился. Ну в Delphi 7 синхронизация устроена именно таким образом: надо постоянно проверять очередь Synchronize"ов и вызывать их (когда есть время).
← →
Suntechnic (2003-06-09 19:08) [15]>kull © (09.06.03 18:46)
А как же Хелп?
там написано: Executes Method within the main VCL thread.
Это если писать только на VCL. Но если взять ситуации описанные в Digitman © (09.06.03 08:53) и (09.06.03 16:32), то как говорил Digitman ©, "не факт" :)
Посмотрите исходники Synchronize. Synchronize диспатчит вызов метода в тот поток, который первым породил объект TThread. А делается это так: В методе Create потока вызывается глобальная ф-ция AddThread, которая порождает окно, если вызывается впервый раз. Далее все вызовы Synchronize через SendMessage отправляют адрес того Thread, который вызвал Synchronize, в ту самую и единственную оконную ф-цию, которая в ответ на это сообщение вызывает тот метод который хранится в FMethod. Но вот если первый раз TThread был пораждён не в основном потоке приложения (скажем мы создали поток через Win API CreateThread), то в результате все вызовы будут происходить в контексте потока, порождённого с помощью CreateThread.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.03 c