Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.12.26;
Скачать: CL | DM;

Вниз

Вынесение запроса к базе в поток   Найти похожие ветки 

 
BorisUK ©   (2002-12-06 07:55) [0]

У меня трехзвенка, хочу вынести запрос с клиента к базе в поток...
Что делаю не так?

Почитал архив - там на все вопросы такого типа "Что сделать чтоб запрос можно было прервать?", "Чтоб прога не подвисала на время выполнения запроса?"
Все советовали поток... ОК
Создал.

В общем поток запускается (о чем сигнализирует метод монитор, показывая какой запрос пошел исполнятся),
какоето время обрабатывыет, а потом выдается ошибка
"Error reading from Socket" такая же ошибка сразу при попытке прервать поток...
При запуске из делфи дебагер перед этой ошибкой успевает еще сказать:
raised exception class EVariantError with message "Variant is not an array"

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

Помогите кто был успешнее в этом деле...
За рабочий пример буду блаодарен больше жизни :)

unit SQLExecThread;

interface

uses
Classes, dm_u, sysutils, wait_u;

type
TSQLExecThread = class(TThread)
private
StrMes : String;
{ Private declarations }
protected
procedure Execute; override;
procedure Monitor;

public
procedure SetSQL(s : String);

end;

implementation
var
SQLText : String;


procedure TSQLExecThread.SetSQL(s : String);
begin
SQLText:= s;
end;

procedure TSQLExecThread.Monitor;
begin
Wait_f.Label1.Caption:= StrMes;
end;

procedure TSQLExecThread.Execute;
var
i : integer;
begin
try
StrMes:=SQLText;
Synchronize(Monitor);
dm.ClientDataSet1.Active:=false;
dm.ClientDataSet1.CommandText:=SQLText;
dm.ClientDataSet1.Active:=true;
except
on E: Exception do
begin
StrMes:="шибка из потока "+e.Message;
Synchronize(Monitor);
end;
end;

if Terminated then
begin
exit;
end
end;

end.


Из главного окна проги делаю обработчик на кнопку

procedure TMain_f.bb_FindPPClick(Sender: TObject);
var
s : String;
begin
s:="Select * from Table1";
try
SQLExecThrd:=TSQLExecThread.Create(true);
SQLExecThrd.SetSQL(s);
SQLExecThrd.Resume;
SQLExecThrd.Priority:=tpLowest;
except
on E:Exception do
Showmessage("Ошибка в главном модуле "+e.message);
end;
//Вначале сделал вот так, но так виснет сразу
{ finally
SQLExecThrd.Terminate;
SQLExecThrd.Free;
end;}
end;


// Прерывание потока
procedure TMain_f.bb_BreakClick(Sender: TObject);
begin
if SQLExecThrd.Suspended then
SQLExecThrd.Resume;
SQLExecThrd.Terminate;
end;


 
ЮЮ ©   (2002-12-06 08:16) [1]

а dm.ClientDataSet1 синхронизировать не надо?

И это называется трехзвенка, когда клиент изменяет текст запроса?
Суть ClientDataSet-а, по-моему, в том, чтобы брать данные у Провайдера, а тот в свою очередь работал с сервером БД


 
BorisUK ©   (2002-12-06 08:19) [2]

Я примерно так и понял, что ктото чтото теперь не успевает передать,
но как синхронизировать... подскажите плз а то у меня затмение :(


 
sniknik ©   (2002-12-06 08:25) [3]

ну есть пару вещей которые я бы изменил (применительно к потоку), по базе думаю это только наметки (проба), а так вроде все нормально.
try
try
SQLExecThrd:=TSQLExecThread.Create(true);
SQLExecThrd.SetSQL(s);
SQLExecThrd.Priority:=tpNormal; //а то тормозить будет
SQLExecThrd.FreeOnTerminate:= false; //чтобы работало завершение как у тебя
SQLExecThrd.Resume;
except
on E:Exception do
Showmessage("Ошибка в главном модуле "+e.message);
end;
// вот это теперь должно работать от FreeOnTerminate
finally
SQLExecThrd.Terminate;
SQLExecThrd.WaitFor; //ждать окончания запроса пока не отработал убивать нельзя
SQLExecThrd.Free;
end;

ну и бработчик в "скобочки" хотя и без этого работает проверял но в хелпе пишут так надо
procedure TSQLExecThread.Execute;
var
i : integer;
begin
CoInitialize(nil);
... код //но его бы посложней просто один запрос можно и асинхронно выполнить чтобы не тормозило
CoUnInitialize();
end;


 
BorisUK ©   (2002-12-06 09:12) [4]

CoInitialize(nil);
CoUnInitialize();
На них матерится.. говорит
-- Undeclared identifier: "CoInitialize"
А так в общем заработало, но как попало :(
Помогли оба совета...
<<ЮЮ ©
Синхронизировал вроде - хотя может не то сделал...
Вынес получение данных в процедуру потока

procedure TSQLExecThread.ResiveData;
begin
dm.CDS_V_DocTree.Active:=true;
wait_f.close;
end;

В execute вызываю её

procedure TSQLExecThread.Execute;
var
i : integer;
begin
try
// CoInitialize(nil);
dm.CDS_V_DocTree.Active:=false;
dm.CDS_V_DocTree.CommandText:=SQLText;
Synchronize(ResiveData);

except
on E: Exception do
begin
StrMes:=e.Message;
Synchronize(Monitor);
end;
end;

if Terminated then
begin
wait_f.close;
exit;
end;
// CoUnInitialize();
end;

Но теперь все работает как до потока было...
Пока данные не получатся вся прога подвисает...
У меня перед запуском потока вызывается формочка с програссбаром, на ней таймер который задает движение на прогрессбаре (чтоб юзеру не скучно было) Так вот он теперь тоже не идет ... Тоесть пока
dm.CDS_V_DocTree.Active:=true не выполнится
зависает все :(

В общем для чего старался - чтоб запрос прерывать можно было и визуализировать процесс ожидания - Того и не вышло пока...

Может что ещё подскажете?


 
sniknik ©   (2002-12-06 11:18) [5]

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

посмотри еще хелп по ADODataSet.ExecuteOptions может это тебе больше подойдет.



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

Текущий архив: 2002.12.26;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.017 c
6-86048
Bishop
2002-10-29 18:48
2002.12.26
Сделать форум.


1-86032
AFrolov
2002-12-16 17:12
2002.12.26
Под средой прога работает а без среды нет....


7-86186
Serg T
2002-09-16 13:17
2002.12.26
Кулер


3-85787
Tankist
2002-12-05 19:17
2002.12.26
массив


4-86233
Yegor Derevenets
2002-11-10 20:58
2002.12.26
Звук в телефонную линию