![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с нитью [D7, WinXP]
thread © (2006-04-04 07:33:00)Раньше с нитями толком не работал. Сейчас столкнулся со странной проблемой. Приведенная ниже реализация нити жутко ступорится и крайне медленно работает, подвешивая всю машину.
Вначале был вариант:
for i:=i to gContacts.Count-1 do
begin
ADOModule.GetAddressForContact('Контакты',gContacts[i],Street,House);
frmMain.AddAddress(Street,House,'',0);
end;
Но по ряду причин, потребовалась его реализация в виде отдельной нити, чтобы не "умервщлять" GUI :)
// описание нити
TLightThread = class(TThread)
private
ThrI,ThrF,ThrE: Integer;
procedure ThreadLightMethod;
public
procedure Execute; override;
end;
[...]
// создание нити
if MassSelect then
begin
LightThread:=TLightThread.Create(True);
LightThread.ThrF:=i;
LightThread.ThrE:=gContacts.Count-1;
LightThread.FreeOnTerminate:=True;
LightThread.Resume;
end;
[...]
{ TLightThread }
procedure TLightThread.ThreadLightMethod;
var
Street,House: String;
begin
// запрос к БД
ADOModule.GetAddressForContact('Контакты',gContacts[ThrI],Street,House);
// ряд операций над GUI
frmMain.AddAddress(Street,House,'',0);
end;
procedure TLightThread.Execute;
var
i: Integer;
begin
for i:=ThrF to ThrE do
begin
ThrI:=i;
Synchronize(ThreadLightMethod);
end;
end;
Кто может сказать в чем тут трабла? ( Трейсил - все в принципе нормально, но НЕРЕАЛЬНО долго... по сравнению с обычным (без нити) вариантом...
balepa (2006-04-04 07:59:00) [1]
> thread (04.04.06 07:53) [9]
> procedure TLightThread.Execute;
> var
> i: Integer;
> Street,House: String;
> begin
> for i:=ThrF to ThrE do
> begin
> ThrI:=i;
> ADOModule.GetAddressForContact('Контакты',gContacts[ThrI],
> Street,House);
> Synchronize(ThreadLightMethod);
> end;
> end;
>
> и действительно, после переноса запросов к БД в нить, ситуация
> изменилась в лучшую сторону. Но почему-то не происходит
> обновления GUI в Synchronize() :(
>
> ладно, буду разбираться. всем спасибо!
Наверно Потому что раньше было все в куче (var i: Integer; Street,House: Stringing;), а теперь в разных процедурах (потоках) или где у тебя там.
thread (2006-04-04 07:53:00) [2]procedure TLightThread.Execute;
var
i: Integer;
Street,House: String;
begin
for i:=ThrF to ThrE do
begin
ThrI:=i;
ADOModule.GetAddressForContact('Контакты',gContacts[ThrI],Street,House);
Synchronize(ThreadLightMethod);
end;
end;
и действительно, после переноса запросов к БД в нить, ситуация изменилась в лучшую сторону. Но почему-то не происходит обновления GUI в Synchronize() :(
ладно, буду разбираться. всем спасибо!
balepa (2006-04-04 07:51:00) [3]Поменьше обращайся к форме и т.д. из потока, а еще лучше вообще не обращаться
MBo (2006-04-04 07:49:00) [4]Execute:
ThrI:=ThrF
цикл пока not Terminated или ThrI<=ThrE
Запрос;
Synchronize(Метод,только общающийся с главной формой );
Inc(ThrI)
конец;
thread (2006-04-04 07:43:00) [5]MBo -> вынести в поток, ты имеешь в виду?
MBo (2006-04-04 07:41:00) [6]У тебя весь код выполняется в главном потоке. В методе, вызываемом через Synchronize, должно быть только кратковременное обращение к элементам, работающим в главном потоке, а долгую операцию запроса нужно вынести.
balepa (2006-04-04 07:41:00) [7]
> thread (04.04.06 07:38) [2]
> :) это крайний вариант =)
Почему крайний то?
Я считаю в вашем случае крайний вариант работать с потоком.
balepa (2006-04-04 07:40:00) [8]ADOModule.GetAddressForContact('Контакты',gContacts[ThrI],Street,House);
// ряд операций над GUI
frmMain.AddAddress(Street,House,'',0);
Наверное из за этого
Description
Synchronize causes the call specified by Method to be executed using the main thread, thereby avoiding multi-thread conflicts. If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure that it executes in the main thread.
Execution of the thread current is suspended while Method executes in the main thread.
thread (2006-04-04 07:38:00) [9]:) это крайний вариант =)
по поводу потока не скажите ничего?
balepa (2006-04-04 07:37:00) [10]for i:=i to gContacts.Count-1 do
begin
ADOModule.GetAddressForContact('Контакты',gContacts[i],Street,House);
frmMain.AddAddress(Street,House,'',0);
Application.ProcessMessage; //и не мучайся
end;