Форум: "Начинающим";
Текущий архив: 2012.04.22;
Скачать: [xml.tar.bz2];
ВнизПграмма "замерзает" пока 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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.003 c