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

Вниз

Покритикуйте мою вторую попытку многопоточного доступа к базе.   Найти похожие ветки 

 
Карелин Артем ©   (2003-10-22 15:53) [0]

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

type TCallBackProc=procedure(Sender:TThread) of object;

unit SQLThread;

interface

uses
Classes, IBDatabase,IBQuery,windows,Sysutils,DB,GTNTypes;

type
TSQLThread = class(TThread)
private
FDataBase: TIBDatabase;
FQuery: TIBQuery;
FTransaction: TIBTransaction;
FCallBack: TCallBackProc;
FPrepareProc: TCallBackProc;
FTerminator: TCallBackProc;
procedure ExecExternal;
procedure ExecCallBack;
procedure ExecTerminator;
procedure HardStop;
{ Private declarations }
public
property DataBase: TIBDatabase read FDataBase write FDataBase;
property Transaction: TIBTransaction read FTransaction write FTransaction;
property Query:TIBQuery read FQuery write FQuery;
property CallBack:TCallBackProc read FCallBack write FCallBack;
property PrepareProc:TCallBackProc read FPrepareProc write FPrepareProc;
property Terminator:TCallBackProc read FTerminator write FTerminator;
constructor Create(const DataBaseName,SQL:String;const QueryParams:TParams;const DBParams:String);
protected
destructor Destroy;override;
procedure Execute; override;
end;

implementation

{ TSQLThread }

constructor TSQLThread.Create(const DataBaseName, SQL: String;
const QueryParams: TParams;const DBParams:String);
begin
inherited Create(true);
DataBase:=TIBDatabase.Create(nil);
Transaction:=TIBTransaction.Create(nil);
DataBase.SQLDialect:=3;
Query:=TIBQuery.Create(nil);
DataBase.DatabaseName:=DataBaseName;
DataBase.LoginPrompt:=False;
DataBase.Params.Text:=DBParams;
DataBase.DefaultTransaction:=Transaction;
Transaction.DefaultDatabase:=DataBase;
DataBase.Open;
Transaction.StartTransaction;
Query.Database:=DataBase;
Query.Transaction:=Transaction;
Query.SQL.Text:=SQL;
Query.Prepare;
Query.Params.AssignValues(QueryParams);
end;

destructor TSQLThread.Destroy;
begin
Query.Free;
Transaction.Rollback;
Transaction.Free;
DataBase.Free;
inherited;
end;

procedure TSQLThread.ExecCallBack;
begin
if Assigned(CallBack) then CallBack(Self);
end;

procedure TSQLThread.ExecExternal;
begin
if Assigned(PrepareProc) then PrepareProc(Self);
end;

procedure TSQLThread.ExecTerminator;
begin
if Assigned(Terminator) then Terminator(Self);
end;

procedure TSQLThread.Execute;
begin
if Assigned(PrepareProc) then Synchronize(ExecExternal);
Query.Open;
while not(Query.Eof) do
begin
if Terminated then Break;
Synchronize(ExecCallBack);
Query.Next;
end;
Synchronize(ExecTerminator);
end;

procedure TSQLThread.HardStop;
begin
try
if Self<>nil then
begin
TerminateThread(Handle,0);
end;
except
end;
end;

end.


 
Digitman ©   (2003-10-22 16:38) [1]


> а ничего интересного придумать не могу


а и не придумывать не нужно)
все давно уже "придумано" : идешь на ibase.ru и ищешь статью с описанием грамотного и корректного решения данной задачи ... никаким TerminateThread() в этом техническом решении и не пахнет

а все что связано с TerminateThread() - не выдерживает никакой критики и чревато серьезными проблемами, вплоть жо краха как процесса сервера так и процесса клиента


 
Digitman ©   (2003-10-22 16:41) [2]


> procedure TSQLThread.HardStop;
> begin
> ...
> if Self<>nil then // любопытно, при каких условиях Self у тебя может быть равным nil
> ...
> end;


 
Fantasist ©   (2003-10-23 01:32) [3]

Как уже заметили, если ты вызываешь метод у объекта равного nil - это уже слишком плохо, чтобы делать проверки внутри метода. TerminateThread НЕ уничтожает объект и НЕ выбрасывает исключения. Кто и когда вызывает Transaction.Commit?


 
Карелин Артем ©   (2003-10-23 15:21) [4]

Digitman © (22.10.03 16:38) [1]
Да нет там принудительного завершения коннекта. Нет! И не смотрел ты не разу http://ibase.ru/v6/ib6faq.htm#threads
Fantasist © (23.10.03 01:32) [3]
Никто и никогда. Данные из этого потока не меняются. И не должны меняться.
Поток используется для заполнения списка данными из запроса или подсчета числа записей, возвращаемых сложным запросом из большой базы. А за время подсчета количества записей из такого запроса пользователь может десять раз поменять условия запроса, если результат поиска его не устраивает. И что мне тогда делать? Забивать всю систему потоками, которые выполняют уже не нужные запросы?


 
ZeroDivide ©   (2003-10-23 16:52) [5]

Мдя... уж...

или подсчета числа записей, возвращаемых сложным запросом из большой базы
А RecordCount на что у датасета?

И что мне тогда делать?
Карелин Артем © (23.10.03 15:21)
Книжки почитать. И понять хотя бы что такое транзакция.


 
Карелин Артем ©   (2003-10-23 17:02) [6]

ZeroDivide © (23.10.03 16:52) [5]
>А RecordCount на что у датасета?
Да просто так видимо сделали. Советуешь делать FetchAll в основном потоке?? Если набор данных получается очень большой (а планируется миллион-другой записей), то сколько на это уйдет времени и памяти?
Время уйдет в бесконечность кстати... А при чем тут транзакции кстати?


 
Digitman ©   (2003-10-23 17:25) [7]


> Карелин Арт


> нет там принудительного завершения коннекта


а причем здесь вообще это ?
ты вопрос как поставил ?

> насчет "правильного" снятия долгого запроса к базе

так ?

и при чем здесь TerminateThread ? какое отношение имеет принудительное терминирование код.потока к термину, логике и механизму "завершению коннекта" ?

> И не смотрел ты не разу

)) а это что по-твоему ?

http://ibase.ru/devinfo/generator.htm#extra


 
Карелин Артем ©   (2003-10-23 17:37) [8]

Digitman © (23.10.03 17:25) [7]
Каюсь, забыл про это. Других способов нет? А то уже больше сотни кило текстов серверной логики накатал. Долго переделывать.


 
Digitman ©   (2003-10-23 17:47) [9]


> Карелин Артем


другие (корректные) способы для IB/FB на сей момент мне неизвестны


> больше сотни кило текстов серверной логики накатал. Долго
> переделывать


не так уж страшен черт, как его малютки)


 
Карелин Артем ©   (2003-10-24 10:04) [10]

Digitman © (23.10.03 17:47) [9]
Придумал значит такое: делать обычный запрос типа select по одному маленькому полю в потоке из компонента TIBSQL. И там последовательно делать Next до конца набора данных или TThread.Terminated. В принципе переделывать много не надо, скорость устраивает, памяти жрет мало и корректно прекратить можно с клиента.



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

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

Наверх




Память: 0.5 MB
Время: 0.025 c
14-42097
ZeroDivide
2003-10-23 10:33
2003.11.13
Кто знает, чем закончилась


1-41593
HydraMarat
2003-10-27 01:38
2003.11.13
Значение типа из строки


3-40995
yus
2003-10-24 15:12
2003.11.13
Защита данных


1-41506
Тимохов
2003-10-28 14:37
2003.11.13
Попрос по clipboard


3-40787
grifon-nn
2003-10-21 22:27
2003.11.13
Индексы Paradox