Текущий архив: 2002.03.28;
Скачать: CL | DM;
ВнизTThread Найти похожие ветки
← →
lipskiy (2002-03-16 01:23) [0]Два вопроса.
1. Метод Synchronize почему нельзя вызвать из основного потока?
2. Если делаю так:
constructor TSomeThread.Create;
begin
inherited Create(True);
FreeOnTerminate:= True;
Self.Priority:= tpHigher;
SomeComponent:= TSomeComponent.Create;
SomeComponent.OnEvent:= SomeCompEvent;
Resume;
end;
и потом в Execute работаю с SomeComponent, то поток отрабатывает нормально, но после завершения стоит только мне сменить активное окно в системе с моего приложения на другое, вылетает ексепшен - типа неверный дескриптор окна.
А вот если две строчки
SomeComponent:= TSomeComponent.Create;
SomeComponent.OnEvent:= SomeCompEvent;
перенести внутрь Execute - в самое начало, то все работает безошибочно. А чем первый-то вариант может быть плох?
← →
kull (2002-03-16 02:03) [1]1. Вообще то Synchronize защищенный метод класса TThread поэтому его можно вызвать только из потомка.
Или переписать его в потомке в секции public.
А в принципе Synchronize и существует для того чтоб вызывать его не из основного потока,а из своего потока. Иначе нет никакого смысла.
2. А здесь я что-то не понял, может еше раз поподробнее?
← →
lipskiy (2002-03-16 02:16) [2]Насчет вызова Synchronize, в принципе, понятно, конечно, но вот в хелпе написано:
If you are unsure whether a method call is thread-safe, call it from within the main VCL thread by passing it to the Synchronize method.
Здесь main VCL thread разве не основная программа?
Ну а на практике потребовалось это вот зачем.
Есть, например, компонентик для закачки файлов с инета. Он создан в дизайн-тайме (невизуальный) и лежит просто на главной форме. Так вот и получается, что я не могу им нормально воспользоваться в потоке в этом случае. А получается только если создавать его вместе с потоком в ран-тайме.
А насчет второго вопроса... Ну, поробую, я и сам ни фига не понял, что произошло.
Так вот, перенес я создание этого компонента для закачки файлов в конструктор потока и стал прогонять. Файл скачался, все ок. Поток завершился, никаких ошибок. Теперь не закрывая программы просто вызвал окно проводника или аську запустил (не важно что) - и моя прога выдает (вернее - Дельфа) что "неверный дескриптор окна" и вываливается совсем.
Решил создать компонент (ну то есть его экземпляр, или как это правильно говориться) не в конструкторе потока, а внутри Execute - перед тем, как собственно стартовать закачку. И вот после этого прога работала без глюков как положено.
Причины я так и не понял.
← →
kull (2002-03-16 02:28) [3]Да действительно странно...
Я таким же образом (в отдельном потоке потоке) работал с базой данных с помощью TConnection и TCursor.
Создавались эти компоненты в основном потоке (при создании формы автоматически), а запрос уже шел в другом потоке и все было в порядке...
← →
lipskiy (2002-03-16 02:54) [4]А как, например, если компонент создан в основном потоке, а обрабатывается в отдельном, и у компонента есть событие, которое возникает периодически во время работы (прогресс закачки, например), так вот как из обработчика этого события вызвать Synchronize - ведь сам обработчик находится в основном потоке?
← →
kull (2002-03-16 03:06) [5]Прогресс закачки, я так понимаю вызывается из потока закачки,
а это значит, что событие обрабатывается не в основном потоке.
Я дела примерно так:
1. создал поток в который передал метод формы.
2. в Execute вызывал этод метод, в котором и велась работа с базой, а также устанавливался индикатор прогресса через Synchronize (его я переопределил как public).
← →
lipskiy (2002-03-16 11:23) [6]
> 1. создал поток в который передал метод формы.
Это как? (не проснулся я еще, что ли...)
← →
kull (2002-03-16 16:03) [7]Ну примерно так:
//unit с потоком
unit Unit2;
interface
uses
Classes;
type
TMyMethod = procedure(Sender:TThread) of object;
TMyThread = class(TThread)
private
{ Private declarations }
FMyMethod: TMyMethod;
protected
procedure Execute; override;
public
constructor Create(MyMethod: TMyMethod); reintroduce;
procedure Synchronize(Method: TThreadMethod);
end;
implementation
{ TMyThread }
constructor TMyThread.Create(MyMethod: TMyMethod);
begin
FMyMethod:=MyMethod;
inherited Create(False);
end;
procedure TMyThread.Execute;
begin
{ Place thread code here }
FMyMethod(Self);
end;
procedure TMyThread.Synchronize(Method: TThreadMethod);
begin
inherited Synchronize(Method);
end;
//unit c формой
uses .......,Unit2;//подключаю мой Thread
TForm1 = class........
.............
//метод
procedure MyFormMethod(Sender:TThread);
............
end;
...........
..........
procedure TForm1.MyFormMethod(Sender:TThread);
begin
while not TMyThread(Sender).Terminated {Terminated тоже можно сделать public или завести свой флаг на форме} do
begin
загрузка данных с периодическим вызовом
TMyThread(Sender).Synchronize(MyProgressMethod);
end;
end;
← →
lipskiy (2002-03-16 16:20) [8]Угу, спасибо, понял принцип.
То есть не напрямик вызывать Synchronize из основного потока, а правой пяткой через левое ухо :)
Да не, нормально. Так и сделаю.
← →
kull (2002-03-16 16:23) [9]Ну я рад, что чем то помог...
Страницы: 1 вся ветка
Текущий архив: 2002.03.28;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.005 c