Форум: "Базы";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];
ВнизПередача данных запроса к БД из потока Найти похожие ветки
← →
galexis © (2004-09-06 13:46) [0]Пытаюсь работать с потоками (TThread). В потоке выполняется запрос к БД FireBird. А что делать с набором данных после этого не знаю. Как передать их в основной поток? Сейчас провожу эксперименты с SendMessage, но думаю что это не выход, да и с ним у меня пока еще ничего не вышло. Приложение у меня MDI, а поток создается из дочернего окна. Как обратиться к элементу редактирования TEdit, который расположен в таком окне?
Помогите разобраться пожалуйста.
← →
Карелин Артем © (2004-09-06 13:51) [1]Разберись с основами синхронизации потоков. Конкретно Synchronize
← →
galexis © (2004-09-06 14:05) [2]
> Карелин Артем ©
Где бы прочитать в интернте про это. У меня есть распечатка главы "Создание многопоточных приложений" из какой то книги. В данный момент как раз открыта на Synchronize. С примером, где сообщение передается непосредственно в основной поток, а я к нему и обратится не могу, форма то дочерняя
← →
Digitman © (2004-09-06 14:13) [3]
> сообщение передается непосредственно в основной поток, а
> я к нему и обратится не могу, форма то дочерняя
???
← →
Карелин Артем © (2004-09-06 14:15) [4]Не надо сообщения мучать. Пиши просто edit1212.text:=запрос.поле1.какстрока в методе, который будешь вызывать посредством Synchronize
← →
galexis © (2004-09-06 14:28) [5]
> Digitman ©
Не могу обратиться к элементу TEditиз потока, ну например надо написать
FindForm.Edit1.Test:=...; Но Форма FindForm у меня MDIChild, т.е. к ней надо обращаться как
MainForm.MDIChildren[0]. А как обратиться к элементу Edit1 на ней?
← →
galexis © (2004-09-06 14:29) [6]>Карелин Артем © Вот к edit1212.text я и не могу обратиться.
← →
galexis © (2004-09-06 14:43) [7]Могу вот так сообщение переслать
SendMessage(MainForm.MDIChildren[0].ActiveControl.Handle,WM_SETTEXT,0,Integer(PChar(cnt)));
Но это не выход. А как можно передать набор данных и поместить его в DBGrid?
← →
Reindeer Moss Eater © (2004-09-06 14:58) [8]TDataSource + TDBGrid
← →
galexis © (2004-09-06 15:16) [9]
> Reindeer Moss Eater ©
Это понятно, а если TDBGrid находится на форме FindForm, которая MDIChild?
← →
Romkin © (2004-09-06 15:29) [10]Элегантный выход - TClientDataset. Удивлены? Все просто, в Execute потока создавайте модуль данных с T...Query и TDatasetProvider (именно в execute ;) ). Делайте, что угодно. Потом просто передайте данные из провайдера в TClientDataSet на форме (эссно в Syncronize). И все. У вас есть набор данных, с которым вы можете делать все. Уже в основном потоке :))
← →
Reindeer Moss Eater © (2004-09-06 15:31) [11]Это понятно, а если TDBGrid находится на форме FindForm, которая MDIChild?
А какая разница где именно она "находится"?
← →
galexis © (2004-09-06 15:41) [12]
> Reindeer Moss Eater ©
Разница в том, что нельзя обратиться к TDBGrid обычным образом, т.е. нельзя написать FindForm.DBGrid1.DataSource.
Форма создается в процессе работы приложения и не имеет имени, к ней можно обратиться как MainForm.MDIChildren[0] Как обратиться при этом к конкретному компоненту, а мне надо DBGrid я не знаю. Точнее знаю. Надо сделать его активным и обращаться к нему как MainForm.MDIChildren[0].ActiveControl. Но это не очень хорошо.
← →
Reindeer Moss Eater © (2004-09-06 15:43) [13]Дык у тебя вопрос про то как найти экземпляр формы.
При чем здесь вся предыдущая канитель со вторичными потоками?
К делу не относящаяся.
← →
galexis © (2004-09-06 15:46) [14]
> Romkin ©
Пока еще до меня не дошло в полной мере, то что вы предложили. Но, по моему, если я расположу TClientDataset на моей форме FindForm, я и к этому компоненту не смогу обратиться. вот если только его расположить на MainForm.
← →
Reindeer Moss Eater © (2004-09-06 15:47) [15]вот если только его расположить на MainForm.
Он там один, а MDI Child"ов - много.
Как делить будем?
← →
galexis © (2004-09-06 15:48) [16]
> Reindeer Moss Eater ©
Ну задача у меня стоит как передать набор данных из вторичного потока в основной. А уж все остальное это попутно.
← →
Reindeer Moss Eater © (2004-09-06 15:49) [17]Никуда наборы данных не передаются.
Они остаются там где были созданы.
Вплоть до закрытия и деструктора.
← →
Digitman © (2004-09-06 15:50) [18]
> galexis © (06.09.04 14:28) [5]
см. [13]
???
← →
galexis © (2004-09-06 16:05) [19]
> Digitman ©
Да я и не спорю. Но и ясности у меня так и нет. Вот выполнился во вторичном потоке у меня запрос к БД. Теперь IBQuery содержит набор данных. На форме из которой был создан вторичный поток есть DBGrid. Как заполнить DBGrid данными из IBQuery вторичного потока?
← →
Reindeer Moss Eater © (2004-09-06 16:06) [20]Как заполнить DBGrid данными из IBQuery вторичного потока?
DBGrid.DataSource:=MySource;
MySource.DataSet:=MyDataSet;
← →
Digitman © (2004-09-06 16:07) [21]
> На форме из которой был создан вторичный поток
почему бы форме, создавшей вторичный поток, не передать параметром в этот поток ссылку на себя ? и искать же ничего не нужно будет !
← →
galexis © (2004-09-06 16:12) [22]
> Digitman ©
Если бы я знал как это сделать? Есть правда в Demos от Delphi примерчик. Там как раз и передаются многие параметры. Опять же все как то мудрено там
← →
Reindeer Moss Eater © (2004-09-06 16:17) [23]Передача параметров - мудрено?
Ну ну.
Стоит ли вообще браться за программирование?
...
with TMyThread.Create(MyDBGrid) do
resume;
...
← →
galexis © (2004-09-06 16:23) [24]
> Reindeer Moss Eater ©
Мудрено в примерчике. Там используется конструктор. Примерчик называется ThreadedQuery.
За программирование браться не стоит, если это не основная работа и не хобби. У меня как раз не то, не то. Я вообще хочу начальником быть :)
← →
Reindeer Moss Eater © (2004-09-06 16:26) [25]Мудрено в примерчике. Там используется конструктор.
Конструкторы везде используются где есть классы.
В том числе и в твоих программах написанных ранее.
Не только в том примерчике.
← →
Digitman © (2004-09-06 16:30) [26]
> Я вообще хочу начальником быть
не то, брат, не то ... настоящие начальники должны как минимум уметь писать "ни то ни другое", ну и опционально - уметь передавать в конструирующий метод произвольного класса (причем по барабану какого - TThread или TSomeClass) некие параметры
← →
Анонимщик © (2004-09-06 16:36) [27]Вот почти один-в-один то, что нужно:
http://www.instantchess.com/?EC=3&EXP=1&FindPl=%C2%EE%E2%EA&SUH=1&Date1=38229&RT2=1#4
← →
Анонимщик © (2004-09-06 16:46) [28]Пардон,
http://www.delphiworld.narod.ru/base/background_db_queries.html
← →
galexis © (2004-09-06 16:47) [29]
> Digitman ©
По поводу передавать в конструирующий метод это все поправимо, а вот начальником стать труднее. Я вот работаю в отделе программного обеспечения в структуре власти. По образованию физик. А два моих начальника (точнее начальник и его зам.) один, врач второй сантехник. А вы мне про ни то ни другое. Мне бы примерчик простенький, или ссылку на статейку по теме.
← →
galexis © (2004-09-06 16:51) [30]
> Анонимщик © (06.09.04 16:46) [28]
О! Вот за это спасибо
← →
galexis © (2004-09-06 16:54) [31]
> Анонимщик ©
Упс! А IBQuery не может работать с TSession :(
← →
Анонимщик © (2004-09-06 16:55) [32]Я же сказал, что почти, а не именно то. Тем более, что тебе для IB сессии не нужны вовсе. Делай отдельный подключения в каждом потоке.
← →
Digitman © (2004-09-06 16:56) [33]
> galexis © (06.09.04 16:47) [29]
я-то ждал иного вопроса - "подскажите ссылку на инф-цию о принципах передачи параметров в методы Делфи-объектов" ... а в ответ - про сантехников и физиков .. печально это
>не основная работа и не хобби
> ..
> в отделе программного обеспечения в структуре власти
поясни, пож., зачем представителю руков.состава заниматься несвойственной ему по должности работой, если она даже не хобби ? у меня только одна мысль в голову - подработка ...
← →
Анонимщик © (2004-09-06 16:58) [34]Как ты все же утомил всех:
unit IBBackGroundQuery;
interface
uses
Classes, IBDataBase, IBQuery, SysUtils, Messages, Forms, DB, Windows;
type
TIBBackGroundQuery = class(TThread)
private
{ Private declarations }
FDBName : String;
FSQLString : String;
FDBParams : TStringList;
FIBDB : TIBDataBase;
FIBT : TIBTransaction;
FIBQSequences: TIBQuery;
FDS : TDataSource;
FQueryException: Exception;
// обработка исключения, связанного с ошибкой выполнения запроса
procedure ShowQryError;
procedure ConnectDataSource;
protected
procedure Execute; override;
public
constructor Create(ADBName: String; ADBParams: TStrings;
const ASQLString: String; const ADS: TDataSource); virtual;
destructor Destroy; override;
end;
implementation
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TIBBackGroundQuery.UpdateCaption;
begin
Form1.Caption := "Updated in a thread";
end; }
{ TIBBackGroundQuery }
constructor TIBBackGroundQuery.Create(ADBName: String; ADBParams: TStrings;
const ASQLString: String; const ADS: TDataSource);
begin
inherited Create(false);
FDBName := ADBName;
FDBParams := TStringList.Create;
FDBParams.Assign(ADBParams);
FSQLString := ASQLString;
FDS := ADS;
FreeOnTerminate := false;
end;
destructor TIBBackGroundQuery.Destroy;
begin
inherited;
FIBDB.Free;
FIBT.Free;
FIBQSequences.Free;
end;
procedure TIBBackGroundQuery.ShowQryError;
begin
Application.ShowException(FQueryException);
end;
procedure TIBBackGroundQuery.ConnectDataSource;
begin
FDS.DataSet := FIBQSequences;
FDS.DataSet.Active := true;
end;
procedure TIBBackGroundQuery.Execute;
begin
{ Place thread code here }
try
FIBDB:= TIBDataBase.Create(nil);
FIBDB.LoginPrompt := false;
FIBT := TIBTransaction.Create(nil);
FIBDB.DatabaseName := FDBName;
FIBDB.Params.Assign(FDBParams);
FDBParams.Free;
FIBT.Params.Clear;
FIBT.Params.Add("read_committed");
FIBT.Params.Add("rec_version");
FIBT.Params.Add("nowait");
FIBDB.DefaultTransaction := FIBT;
FIBT.DefaultDatabase := FIBDB;
FIBQSequences:= TIBQuery.Create(nil);
FIBQSequences.Database := FIBDB;
FIBQSequences.Transaction := FIBT;
FIBQSequences.SQL.Clear;
FIBQSequences.SQL.Add(FSQLString);
FIBQSequences.Open;
Synchronize(ConnectDataSource);
except
FQueryException := ExceptObject as Exception;
Synchronize(ShowQryError);
end;
end;
end.
← →
galexis © (2004-09-06 17:03) [35]
> Digitman ©
Так и есть, кушать хочется!
← →
galexis © (2004-09-06 17:12) [36]
> Анонимщик © (06.09.04 16:58) [34]
Только не убивайте..
Можно теперь кусочек кода создания этого потока?
← →
Анонимщик © (2004-09-06 17:19) [37]Интересно, что ты с ним делать будешь?
var
IBBackQ: TIBBackGroundQuery;
begin
IBBackQ := TIBBackGroundQuery.Create("127.0.0.1:c:\1.gdb", nil, "select g from alexis", MyDS);
← →
Digitman © (2004-09-06 17:20) [38]это называется - "дай г., дай ложку"
← →
galexis © (2004-09-06 17:29) [39]
> Анонимщик ©
А как передавать параметры БД, которые nil?
← →
Reindeer Moss Eater © (2004-09-06 17:33) [40]Усыпите его кто-нибудь уже.
← →
Анонимщик © (2004-09-06 17:37) [41][39] galexis © (06.09.04 17:29)
> Анонимщик ©
А как передавать параметры БД, которые nil?
Я не знаю.
← →
galexis © (2004-09-06 17:54) [42]Хорошо, что мы в разных городах (я надеюсь). А то вот так с работы выйдешь и убьют :)
Всем спасибо. Где еще о потоках за один день столько узнаешь. Может это еще кому нибудь пригодится.
← →
galexis © (2004-09-06 17:58) [43]Анонимщик ©
Работает ведь все! Спасибо огромное!
← →
Анонимщик © (2004-09-06 18:02) [44]Это тебе так только кажется. Я там специально сделал две ошибки. Будь готов к AccessViolation.
← →
galexis © (2004-09-07 09:54) [45]
> Анонимщик © (06.09.04 18:02) [44]
Я в принципе понял как работать с потоками и что это за штука. Сейчас буду адаптировать код к своей программе, многое переделать придется. Может и ошибки тогда найдутся. А затеяно это все для того, чтобы клиентское приложение не замирало и была возможность нажать кнопку отмена в процессе выполнения запроса.
← →
galexis © (2004-09-07 10:04) [46]Столкнулся с приятной загадкой. Запрос во вторичном потоке выполняется раз в 10 быстрее чем в основном. Т.е. раньше у меня запрос выполнялся в основном потоке около 2 минут, а сейчас по моему секунд за 20 справился. К чему бы это?
← →
Digitman © (2004-09-07 10:32) [47]
> была возможность нажать кнопку отмена в процессе выполнения
> запроса
и что ты намерен делать в обработчике нажатия кнопки Отмена ?
← →
Rule © (2004-09-07 10:42) [48]Digitman © (07.09.04 10:32) [47]
Application.terminate :))))
← →
Digitman © (2004-09-07 10:46) [49]
> Rule © (07.09.04 10:42) [48]
тебе-то смешно, а автору "жениться")
← →
Rule © (2004-09-07 10:49) [50]Digitman © (07.09.04 10:46) [49]
Ну шош сделаешь, настроение сегодня хорошее :)
← →
galexis © (2004-09-07 11:03) [51]
> Digitman © (07.09.04 10:32) [47]
По кнопке Отмена запущу еще один запрос в еще одном потоке, который будет менять значения предварительно созданного генератора. В основном запросе будет проверка на значение этого генератора
← →
Анонимщик © (2004-09-07 11:31) [52]Ну вы посмотрите как он буквально за день на глазах прямо вырос.
galexis
Значение генератора проверяй, конечно, но только смотри, чтобы кто-нибудь другой в то же время тот же запрос не запустил. А вот почему выполняется быстрее - попробуй сам догадаться.
← →
galexis © (2004-09-07 12:40) [53]
> Анонимщик © (07.09.04 11:31) [52]
> Значение генератора проверяй, конечно, но только смотри,
> чтобы кто-нибудь другой в то же время тот же запрос не запустил
Об этом я как то и не подумал. И как же быть?
Кстати, там в коде стоитFreeOnTerminate := false;
Почему не true? У меня конечно на компе памяти много, но вот у пользователей не много. Правда, что теперь моя программа не будет работать под 98?
← →
galexis © (2004-09-07 12:42) [54]И всетаки почему быстрее стал выполнятся запрос? FB стоит на сервере, ему то ведь все равно из какого потока ему послан запрос.
← →
Анонимщик © (2004-09-07 14:54) [55]> Значение генератора проверяй, конечно, но только смотри,
> чтобы кто-нибудь другой в то же время тот же запрос не запустил
Об этом я как то и не подумал. И как же быть?
Корректного решения нет. Можно попытаться прибить поток, но гаранти нет.
Кстати, там в коде стоит FreeOnTerminate := false;
Почему не true? У меня конечно на компе памяти много, но вот у пользователей не много.
Поставь true, тебе в этом никто помешать не может.
Правда, что теперь моя программа не будет работать под 98?
Неправда.
И всетаки почему быстрее стал выполнятся запрос? FB стоит на сервере, ему то ведь все равно из какого потока ему послан запрос.
ibase.ru - читай о IB вообще и транзакциях в частности
← →
galexis © (2004-09-08 10:55) [56]Часть программы переделал. Поток запускается, данные пересылаются в DbGrid. При желании кнопкой отмена можно отменить поиск. Но в старой версии программы после того как отобранные по запросу данные отображались в DBGrid, пользователь при желании мог посмотреть более подробную информацию щелкнув два раза на записи в DBGrid. После чего формировался новый запрос с условием по полю ID из IBQuery, которое (ID) в DBQuery не отображалось. А сейчас у меня нет IBQuery, из которого я бы мог взять это поле, есть только DataSource. Как поступить?
← →
galexis © (2004-09-08 12:41) [57]С предыдущим вопросом спарвился, может и не очень хорошо, да ладно. Добавил в DBGrid требуемые поля и сделал их свойство Visible:=False.
Теперь появился еще вопрос. При запуске программы компонент IBDatabase требует пароль. Пользователь вводит пароль, открывается соединение и программа работает. Для вторичного потока нужно свое соединение. Хотел взять параметры из основного, но не могу получить пароль. Как это сделать? Можно ли узнать в программе какой пароль ввел польователь?
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];
Память: 0.61 MB
Время: 0.039 c