![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Пграмма "замерзает" пока TThread не завершится [WinXP]
гия © (2011-12-28 12:44:00)Здравствуйте
Пишу пограмму в Дельфи ХЕ под Windows XP в которой приходится выполнять долгие селекты.
Чтобы программа не "замерзала" пока селект не выполнится написал обработчик
procedure Button1Click(Sender: TObject);
begin
with Query do begin
Close;
SQL.Clear;
SQL.Add('SELECT .....');
TMyThread.Create(Query);
Application.ProcessMessages;
end;
end;
TMyThread описан следующим образом:
unit uMyThread;
interface
uses
Classes {$IFDEF MSWINDOWS} , Windows {$ENDIF}, Ora, Unit1;
type
TMyThread = class(TThread)
private
FQuery: TOraQuery;
protected
procedure Execute; override;
public
constructor Create(Query: TOraQuery);
end;
implementation
{ TMyThread }
constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(False);
FQuery := Query;
Priority := tpNormal;
FreeOnTerminate:= True;
// Resume;
Execute;
end;
procedure TMyThread.Execute;
begin
NameThreadForDebugging('MyThread');
{ Place thread code here }
FQuery.Open;
end;
end.
Однако программа все равно "замерзает" пока селект не выполнится.
Что надо сделать что бы селект реально выполнялся бы в "background"-е, а прграмма продолжала бы выполнять другие вещи
OW (2011-12-29 14:45:00) [1]
> что такое ThQ? и где надо его описать?
это твой класс.
ThQ ~ TMyКАКОЙТОClass = class(TThread)
что я писал - не под копи/паст, а как пример для подумать
MBo (2011-12-29 13:56:00) [2]Посмотри пример
http://delphi.about.com/od/kbthread/a/query_threading.htm
только учти, что строчка в Execute с ListBox.Items.Insert - нехорошая, это нужно делать в методе, вызываемом через Synchronize.
Остальное вроде сделано по-божески.
гия (2011-12-29 13:32:00) [3]аля так
ThQ := ThSQuery.Create(true);
ThQ.S := Session.ConnectString;
ThQ.SQL := S;
ThQ.Window := Handle;
ThQ.Msg := ESBD_COMPLETE_QUERY_SUBJECT;
ThQ.Resume;
что такое ThQ? и где надо его описать?
Сергей М. (2011-12-28 17:47:00) [4]
> Если используются визуальные элементы, то через Synchronize
Можно и файберы задействовать, тогда можно спокойно лезть туда из неосновного потока. Но сложновато будет и овчинка выделки вряд ли стоит.
гия (2011-12-28 17:41:00) [5]Спасибо всем за оказанную помощь.
Сеглдня уже конец рабочего дня. Завтра с утра займусь
OW (2011-12-28 17:33:00) [6]поток сознания BEGIN
ThSQuery = class(TThread)
наобъявить что надо
FQ: TSmartQuery;
FC: TOraSession;
FS: string;
FSQL: string;
FHWND: Cardinal;
FMsg: Cardinal;
написать удобных методов
procedure ThQuery.SetSQL(const Value: string);
begin
if FC = nil then
begin
FC := TOraSession.Create(nil);
FC.ConnectString := FS;
FC.Options.Net := True;
FC.Open;
end;
if FQ = nil then
begin
FQ := TSmartQuery.Create(nil);
FQ.Session := FC;
end;
FQ.SQL.Text := Value;
end;
и юзать аля
ThQuery.SQL := 'select 1 from dual'
а тут и соединение и набор данных создастся закулисами
или, если было определено - не создаться.
FHWND: Cardinal;
FMsg: Cardinal;
инициализируется перед стартом потока, смысл - кому и о чем сообщить
аля так
ThQ := ThSQuery.Create(true);
ThQ.S := Session.ConnectString;
ThQ.SQL := S;
ThQ.Window := Handle;
ThQ.Msg := ESBD_COMPLETE_QUERY_SUBJECT;
ThQ.Resume;
а в потоке
procedure ThQuery.Execute;
begin
if FQ <> nil then
begin
FQ.Open;
end;
SendMessage(FHWND, FMsg, 0, Integer(FQ)); //передаем указатель на набор данных
FImBisy := False;
end;
Окно FHWND ожидает сообщения FMsg и знает, что оно указатель на результат запроса.
Там этот LParam и приводится к TSmartQuery
Form1 = class(TFORM)
procedure CompleteQuery(var Msg: TMessage); message ESBD_COMPLETE_QUERY_SUBJECT;
procedure TfrmSubject.CompleteQuery(var Msg: TMessage);
oqBase := TSmartQuery(Pointer(Msg.LParam));
только тут поток прибивается тогда, когда набор будет не нужен,
т.к. мы сейчас смотрим в "его" набор.
У меня прибивался когда пользователь новый просил набор
поток сознания END
как-то так :)
MBo (2011-12-28 17:14:00) [7]>хоть текст запроса и пароль для коннекции можно передать из основного Thread-а?
Да
>как получить в таком случае в основном Thread-е результаты выполненного запроса?
Смотря что при этом делается. Если используются визуальные элементы, то через Synchronize
гия (2011-12-28 16:46:00) [8]и еще как получить в таком случае в основном Thread-е результаты выполненного запроса?
гия (2011-12-28 16:16:00) [9]Это сделаю. Но хоть текст запроса и пароль для коннекции можно передать из основного Thread-а?
Медвежонок Пятачок (2011-12-28 16:06:00) [10]создавать орасешшон внутри execute. и там же квери.
гия (2011-12-28 15:54:00) [11]г-н Сергей М.
Спасибо за подсказку
FQuery := Query; // конекшн создан в главном треде
Как поступить? Передать Thread-у указатель на TOraSession и присвоить значение уже в Thread-е?
И второе когда в место Execute написал Resume получаю сообщение об ошибке "Thread Error: The Handle is Invalid(6)"
Медвежонок Пятачок (2011-12-28 15:46:00) [12]а вот здесь тебя скорее всего ждет засада
это будет уже другая засада.
текущая засада:
Пграмма "замерзает" пока TThread не завершится
Сергей М. (2011-12-28 15:36:00) [13]constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(True);
FQuery := Query; // а вот здесь тебя скорее всего ждет засада, если коннекшн, на который ссылается Query, создан в другом треде
FreeOnTerminate:= True;
Resume;
end;
Медвежонок Пятачок (2011-12-28 15:34:00) [14]constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(True);
FQuery := Query;
Priority := tpNormal;
FreeOnTerminate:= True;
Resume;
end;
гия (2011-12-28 15:12:00) [15]Госпада
Подскажите как правильно написать
Сергей М. (2011-12-28 14:09:00) [16]
> реально-то все равно запускаются два экзекута
Ну это да.
> сначала во вторичном, затем в основном
Не факт. Хотя сути это конечно не меняет.
Медвежонок Пятачок (2011-12-28 14:04:00) [17]но реально-то все равно запускаются два экзекута.
сначала во вторичном, затем в основном.
Сергей М. (2011-12-28 14:01:00) [18]
> Причем у него экзекут выполняется дважды
> второй раз - таки во вторичном
Это вряд ли.
Во вторичном экзекут наверняка обламывается на FQuery.Open
Медвежонок Пятачок (2011-12-28 13:57:00) [19]Причем у него экзекут выполняется дважды.
Один раз в главном потоке, а второй раз - таки во вторичном.
constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create( False);
...
//Resume;
Execute;
end;
Anatoly Podgoretsky (2011-12-28 13:37:00) [20]> Медвежонок Пятачок (28.12.2011 13:17:02) [2]
При этом управление вернется только после того, как закончится Execute