Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
4-1093715324
Valdemar
2004-08-28 21:48
2004.10.03
Защита CD от копирования


4-1093810369
cerber1
2004-08-30 00:12
2004.10.03
чтение СОМ портов


14-1095306740
КаПиБаРа
2004-09-16 07:52
2004.10.03
Опрос - Когда вы впервые пришли на этот форум?


1-1095393638
Артем К.
2004-09-17 08:00
2004.10.03
Здравствуйте, уважаемые мастера. Как изменить шрифт Hinta?


4-1093095106
debuger
2004-08-21 17:31
2004.10.03
Приоритет в Вин2к





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский