Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Вниз

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

 
Карелин Артем   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.035 c
1-41711
MaG
2003-11-03 19:16
2003.11.13
HTML


3-40898
axx
2003-10-20 12:49
2003.11.13
Как переставить указатель на нужную запить DBGrid a


1-41299
Vasek
2003-10-30 12:58
2003.11.13
Fast Report


8-41747
Urvin
2003-07-05 22:38
2003.11.13
Pen Mode и методы рисования


14-41900
Ломброзо
2003-10-21 13:58
2003.11.13
Jabberwock





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский