Текущий архив: 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.47 MB
Время: 0.033 c