Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.04.22;
Скачать: CL | DM;

Вниз

Пграмма "замерзает" пока TThread не завершится   Найти похожие ветки 

 
гия   (2011-12-28 12:44) [0]

Здравствуйте
Пишу пограмму в Дельфи ХЕ под 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"-е, а прграмма продолжала бы выполнять другие вещи


 
RWolf ©   (2011-12-28 13:11) [1]

надо правильно использовать класс TThread.
пример есть в Demos\Threads.


 
Медвежонок Пятачок ©   (2011-12-28 13:17) [2]

твой экзекут вызван из главного потока а значит и выполняется в нем.
а это значит что сам поток теперь нахрен не нужен.
его можно просто выкинуть, и просто вызывать FQuery.Open из главного


 
Anatoly Podgoretsky ©   (2011-12-28 13:37) [3]

> Медвежонок Пятачок  (28.12.2011 13:17:02)  [2]

При этом управление вернется только после того, как закончится Execute


 
Медвежонок Пятачок ©   (2011-12-28 13:57) [4]

Причем у него экзекут выполняется дважды.
Один раз в главном потоке, а второй раз - таки во вторичном.

constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(False);
...
//Resume;
Execute;
end;


 
Сергей М. ©   (2011-12-28 14:01) [5]


> Причем у него экзекут выполняется дважды
> второй раз - таки во вторичном


Это вряд ли.
Во вторичном экзекут наверняка обламывается на FQuery.Open


 
Медвежонок Пятачок ©   (2011-12-28 14:04) [6]

но реально-то все равно запускаются два экзекута.
сначала во вторичном, затем в основном.


 
Сергей М. ©   (2011-12-28 14:09) [7]


> реально-то все равно запускаются два экзекута


Ну это да.


> сначала во вторичном, затем в основном


Не факт. Хотя сути это конечно не меняет.


 
гия   (2011-12-28 15:12) [8]

Госпада
Подскажите как правильно написать


 
Медвежонок Пятачок ©   (2011-12-28 15:34) [9]

constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(True);
FQuery := Query;
Priority := tpNormal;
FreeOnTerminate:= True;
Resume;
end;


 
Сергей М. ©   (2011-12-28 15:36) [10]

constructor TMyThread.Create(Query: TOraQuery);
begin
inherited Create(True);
FQuery := Query; // а вот здесь тебя скорее всего ждет засада, если коннекшн, на который ссылается Query, создан в другом треде
FreeOnTerminate:= True;
 Resume;
end;


 
Медвежонок Пятачок ©   (2011-12-28 15:46) [11]

а вот здесь тебя скорее всего ждет засада

это будет уже другая засада.
текущая засада:
Пграмма "замерзает" пока TThread не завершится


 
гия   (2011-12-28 15:54) [12]

г-н Сергей М.
Спасибо за подсказку
FQuery := Query; // конекшн создан в главном треде
Как поступить? Передать Thread-у указатель на TOraSession и присвоить значение уже в Thread-е?
И второе когда в место Execute написал Resume получаю сообщение об ошибке "Thread Error: The Handle is Invalid(6)"


 
Медвежонок Пятачок ©   (2011-12-28 16:06) [13]

создавать орасешшон внутри execute. и там же квери.


 
гия   (2011-12-28 16:16) [14]

Это сделаю. Но хоть текст запроса и пароль для коннекции можно передать из основного Thread-а?


 
гия   (2011-12-28 16:46) [15]

и еще как получить в таком случае в основном Thread-е результаты выполненного запроса?


 
MBo ©   (2011-12-28 17:14) [16]

>хоть текст запроса и пароль для коннекции можно передать из основного Thread-а?
Да

>как получить в таком случае в основном Thread-е результаты выполненного запроса?
Смотря что при этом делается. Если используются визуальные элементы, то через Synchronize


 
OW ©   (2011-12-28 17:33) [17]

поток сознания 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
как-то так :)


 
гия   (2011-12-28 17:41) [18]

Спасибо всем за оказанную помощь.
Сеглдня уже конец рабочего дня. Завтра с утра займусь


 
Сергей М. ©   (2011-12-28 17:47) [19]


> Если используются визуальные элементы, то через Synchronize


Можно и файберы задействовать, тогда можно спокойно лезть туда из неосновного потока. Но сложновато будет и овчинка выделки вряд ли стоит.


 
гия   (2011-12-29 13:32) [20]

аля так
ThQ := ThSQuery.Create(true);
ThQ.S := Session.ConnectString;
ThQ.SQL := S;
ThQ.Window := Handle;
ThQ.Msg := ESBD_COMPLETE_QUERY_SUBJECT;
ThQ.Resume;

что такое ThQ? и где надо его описать?


 
MBo ©   (2011-12-29 13:56) [21]

Посмотри пример
http://delphi.about.com/od/kbthread/a/query_threading.htm

только учти, что строчка в Execute с ListBox.Items.Insert  - нехорошая, это нужно делать в методе, вызываемом через  Synchronize.

Остальное вроде сделано по-божески.


 
OW ©   (2011-12-29 14:45) [22]


> что такое ThQ? и где надо его описать?

это твой класс.
ThQ ~ TMyКАКОЙТОClass = class(TThread)
что я писал - не под копи/паст, а как пример для подумать



Страницы: 1 вся ветка

Текущий архив: 2012.04.22;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.007 c
3-1274355052
Ulugbek
2010-05-20 15:30
2012.04.22
Помогите мне спроектировать базу для учет денег


2-1323823424
Валентина
2011-12-14 04:43
2012.04.22
распределение средств между предприятиями


15-1324025146
Win7_comp
2011-12-16 12:45
2012.04.22
Windows 7 64x отключается экран


2-1325168892
Gu
2011-12-29 18:28
2012.04.22
Pointer


15-1324302501
aka
2011-12-19 17:48
2012.04.22
поиск по списку слов.