![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
dll [D7, XP]
Sw © (2014-08-28 13:15:00)Помогите пожалуйста!
в dll:
IBDB:=TIBDatabase.Create(Application);
IBDB.Params.Clear;
IBDB.LoginPrompt:=False;
IBDB.DatabaseName:='D:\Test\DB.fdb';
IBDB.Params.Add('user_name=SYSDBA');
IBDB.Params.Add('password=masterkey');
IBDB.Params.Add('lc_ctype=win1251');
IBDB.Connected:=true;
IBTR:=TIBTransaction.Create(Application);
IBTR.DefaultDatabase:=IBDB;
if IBDB.Connected then ShowMessage('e');
из основной программы вызываю dll-ky, все нормально отрабатывает, ошибок не выдает, появляется сообщение 'e', т.е. я понимаю, что соединение с базой установлено.
Дальше если в исходный код добавить:
iq:=TIBQuery.Create(Application);
iq.Database:=IBDB;
iq.Transaction:=IBTR;
iq.SQL.Text:= 'select id from cs';
iq.Open;
ругается на память ...инструкция по адресу ...обратилась к памяти....Runtime error
ВладОшин (2014-09-17 11:15:00) [1]
> можно применять некие переменные
желательно простые, типа int/byte и т.п.
потом, у тебя в потоке
fm.IBDB:=TIBDatabase.Create(Application);
т.е. обращение к другому потоку, vcl
в принципе не страшно, но не знай как работает TIBDatabase (не юзал IB)
возможно, следует создать TIBDatabase чисто в потоке, а в основном потоке не создавать, а приравнять к созданному. Поток тогда не надо уничтожать, естественно.
т.е. поток создает, соединяется и предоставляет свой объект другим
из плюсов - можно создать еще и еще потоки-соединяльщики и каждый работает паралльльно (надо только следить за ненужными и настройками БД на кол-во с одного места коннектов:). Тут можно какую функцию написать, возвращающую первый свободный коннект, или создавая новый. В общем фантазий - полет)
тоже не знаю насколько это правильно(пусть поправит кто), но работает пока
ВладОшин (2014-09-17 11:01:00) [2]
> убираю синхронайз...посылаю Message и основной поток в случае
> отсутствия соединения с базой должен уничтожить поток-соединяльщик.
> .Вы думаете так сработает?
да
но не знаю насколько правильно. Но сам так делал :)
> А такая конструкция не работает:если нет соединения с базой,
> тогда F:=false; и на кнопку
>
боюсь, не понял
но можно применять некие переменные, при условии, что они будут писаться только одним каким-либо потоком. Остальные потоки только читать ее.
опять же - не знаю насколько правильно. Но сам так делал :)
icWasya (2014-09-17 09:16:00) [3]вместо
ConnectThread.Execute;надоConnectThread.Resume;
Sw (2014-09-17 08:39:00) [4]спасибо за помощь в направлении движения, это мне конечно надо поизучать...
> сейчас второй поток работает в контексте основного потока
понятно...сложилась наконец-то картинка...не доходило
мне вот что еще непонятно..
убираю синхронайз...посылаю Message и основной поток в случае отсутствия соединения с базой должен уничтожить поток-соединяльщик..Вы думаете так сработает? А такая конструкция не работает:если нет соединения с базой, тогда F:=false; и на кнопку
ConnectThread:=TConnectThread.Create(true);
ConnectThread.Priority:=tpNormal;
ConnectThread.Execute;
if not F then
begin
ConnectThread.FreeOnTerminate:=true;
ConnectThread.Terminate;
Exit;
end
else...
не сработает, потому что F не словит из другого потока?
ВладОшин (2014-09-16 16:29:00) [5]сейчас второй поток работает в контексте основного потока
а я имею ввиду аля так
procedure TConnectThread.ConnectLO; //подключение к базе
....
fm.IBDB.Open;
----
тут сообщение(Message или ThreadMessage) об успешном открытии
----
except
on E: Exception do
begin
тут сообщение(Message или ThreadMessage) об ошибке
===========
Tfm
...
procedure bla-bla ; message WM_ТВОЯ_МЕССАГА
=====
идеология:
TConnectThread запускается без синхронайза
TConnectThread начинает соединятся и отправляет мессагу по факту да/нет
основной поток ловит мессагу и решает что делать
ВладОшин (2014-09-16 16:14:00) [6]
> procedure TConnectThread.Execute;
> begin
> Synchronize(ConnectLO);
> end;
и зачем тогда поток?
Sw (2014-09-16 12:59:00) [7]
> а когда находит - все ok?
да, приведу код...может что не так...но отрабатывает нормально
если найдет базу
TConnectThread = class(TThread)
private
protected
procedure Execute; override;
procedure ConnectLO;
end;
var
ConnectThread: TConnectThread;
F:boolean;
procedure TConnectThread.ConnectLO; //подключение к базе
var n,n1:IXMLNode;
SL: TStringList;
DS,Path_DB:string;
begin
try
F:=false;
fm.XMLDocument1.FileName:='D:\test.xml';
fm.XMLDocument1.Active:=true;
n:=fm.XMLDocument1.ChildNodes.FindNode('Config'); //Имя секции
n1:=n.ChildNodes.FindNode('DB'); //Имя вложенной секции
SL:=TStringList.Create;
SL.Delimiter := ';';
SL.DelimitedText := n1.XML;
DS := SL.Values['DataSource'];
Path_DB:=DS+':D:\test.fdb';
fm.IBDB:=TIBDatabase.Create(Application);
fm.IBDB.Params.Clear;
fm.IBDB.LoginPrompt:=False;
fm.IBDB.DatabaseName:=Path_DB;
fm.IBDB.Params.Add('user_name=SYSDBA');
fm.IBDB.Params.Add('password=masterkey');
fm.IBDB.Params.Add('lc_ctype=win1251');
fm.IBDB.Connected:=false;
fm.IBDB.Close;
fm.IBDB.Open;
except
on E: Exception do
begin Application.MessageBox('Не удалось создать подключение к базе данных.','Сообщение',MB_OK+MB_ICONERROR);
SL.Free;
fm.IBDB.Free;
ConnectThread.FreeOnTerminate:=true;
ConnectThread.Terminate;
Exit;
end;
end;
SL.Free;
F:=true;
end;
procedure TConnectThread.Execute;
begin
Synchronize(ConnectLO);
end;
//******************************************************************************
procedure Tfm.BtnImportClick(Sender: TObject); //Загрузка данных из БД
begin
//подключение к базе
ConnectThread:=TConnectThread.Create(true);
ConnectThread.Priority:=tpNormal;
ConnectThread.Execute;
if not F then begin Exit;end else
try
IBTR:=TIBTransaction.Create(Application);
IBTR.DefaultDatabase:=IBDB;
if not IBTR.InTransaction then IBTR.StartTransaction;
iqTRS:=TIBQuery.Create(Application);...........
ВладОшин (2014-09-16 09:18:00) [8]
> сли не находит базу по сети.
а когда находит - все ok?
т.е. а было так, что нашел, и все при этом было все ok?
Поток может помочь.
Не знаю правильно-нет, но как то делал, что поток соединялся, и возвращал мессагой указатель на соединение. Поток-пользователь соответственно ждал мессагу сколько то времени, если дожидался, то приводил полученный указатель к нужному и юзал, а если нет, то завершение программы
Из минусов - поток-соединяльщик потом все время работает.
( Ну там он у меня на самом деле пулом был, там несколько соединений было с постоянными запросами вида select "какая_нибудь_ерунда" по ним, что бы ОСь/сервер не отключали долго не используемое соединение )
Sw (2014-09-16 08:24:00) [9]вот думаю, если реализовать подключение в отдельном потоке и если not IBDB.Connected тогда убить процесс...и один хрен...все-тоже самое...я так понимаю,TIBDatabase не освобождает ресурсы, ждет ответа сервера..не закрывает socket...Может кто-нить подскажет, как бы корректно обработать выход из dll, если нет соединения с базой..
Sw (2014-09-02 07:33:00) [10]Если не находит базу по сети...выдаст сообщение и главное приложение зависает...хотя в диспетчере задач не отображается, что "не отвечает"...просто остается серый фон от интерфейса dll и ничего нельзя с этим сделать, пока не снимешь задачу...
try
...
IBDB.Open;
except
on E: Exception do
begin Application.MessageBox('Не удалось создать подключение к базе данных. ','Сообщение',MB_OK+MB_ICONERROR);
IBDB.Free;
Exit;
end;
end;
интересно, что dll-ка работает, ее можно закрыть без проблем ...а главное приложение сразу виснет...
Может чем поможете? Что с этим делать?
Sw (2014-08-29 11:01:00) [11]доступа к исходнику exe у меня нет..
заработало вот так:
IBDB:=TIBDatabase.Create(Application);
IBDB.Params.Clear;
IBDB.LoginPrompt:=False;
IBDB.DatabaseName:='localhost:D:\Test\DB.fdb';
IBDB.Params.Add('user_name=SYSDBA');
IBDB.Params.Add('password=masterkey');
IBDB.Params.Add('lc_ctype=win1251');
IBDB.Connected:=false;
IBDB.Close;
IBDB.Open;
IBTR:=TIBTransaction.Create(Application);
IBTR.DefaultDatabase:=IBDB;
if not IBTR.InTransaction then IBTR.StartTransaction;
iq:=TIBQuery.Create(Application);
iq.Database:=IBDB;
iq.Transaction:=IBTR;
iq.Close;
iq.SQL.Text:='select id from cs';
iq.Open;
iq.First;
if IBTR.InTransaction then iq.Transaction.Commit;
IBDB.Close;
iqs.Free;
IBTR.Free;
IBDB.Free;
junglecat (2014-08-29 09:58:00) [12]Зачем Application в качестве владельца? Лучше создавать при загрузке DLL (в DLL_PROCESS_ATTACH) удалять при выгрузке.
И exe и dll собраны с runtime packages?
junglecat (2014-08-29 09:46:00) [13]а сам запрос 'select id from cs' работает?
Sw (2014-08-29 05:16:00) [14]извиняюсь..
> на какой строке?
iq.Open;
Sw (2014-08-29 05:10:00) [15]если после этого кода:
IBTR:=TIBTransaction.Create(Application);
IBTR.DefaultDatabase:=IBDB;
if IBDB.Connected then ShowMessage('e');
добавить:
iq:=TIBQuery.Create(Application);
iq.Database:=IBDB;
iq.Transaction:=IBTR;
iq.SQL.Text:= 'select id from cs';
iq.Open;
тогда возникнет ошибка
> исходный код dll?
да
junglecat (2014-08-28 13:47:00) [16]на какой строке?
> в исходный код добавить
исходный код dll?