Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Вниз

Messages & TThread   Найти похожие ветки 

 
Dynamit   (2002-07-25 14:01) [0]

Уважаемые Мастера, помогите: не обрабатываются сообщения, посланные потоку (ThreadID) командой PostThreadMessage.
Вот как тут не плакать :(


 
Digitman   (2002-07-25 15:17) [1]

код-то где ?


 
Dynamit   (2002-07-25 16:07) [2]

unit UQThread;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, BDE;

type
TFQThread = class(TForm)
{...}
private
{ Private declarations }
{...}
UCmd: LongInt;
public
{ Public declarations }
end;

Function CreateQuery(const Number: Integer; const ASQL: String; AHndl: THandle): THandle;

implementation

{$R *.DFM}

Type TQueryThread = class(TThread)
private
QueryForm: TFQThread;
procedure Term(Sender: TObject);
Procedure PMEndThread(var Msg: TMessage); message PM_ENDTHREAD;
Procedure PMThreadCmd(var Msg: TMessage); message PM_THREADCMD;

protected
procedure Execute; override;
public
constructor Create(AQueryForm: TFQThread);
end;

constructor TQueryThread.Create(AQueryForm: TFQThread);
begin
QueryForm := AQueryForm;
FreeOnTerminate := True;
inherited Create(True);
end;

procedure TQueryThread.Execute;
begin
Try
with QueryForm do
begin
While (Not Terminated) Do
Begin
If UCmd=1 Then
Begin
{...}
UCmd:=0;
End Else
Sleep(100);
End;
End;
Finally
{...}
End;
end;

procedure TQueryThread.Term(Sender: TObject);
Begin
{...}
End;

procedure TQueryThread.PMEndThread(var Msg: TMessage);
begin
self.Terminate;
end;

Procedure TQueryThread.PMThreadCmd(var Msg: TMessage);
Begin
{...}
QueryForm.UCmd:=1;
End;


Function CreateQuery(const Number: Integer; const ASQL: String; AHndl: THandle): THandle;
var
QueryForm: TFQThread;
begin
QueryForm := TFQThread.Create(Application);
QueryForm.Visible:=False;
With TQueryThread.Create(QueryForm) Do
Begin
Result:=ThreadID;
QueryForm.UNum:=Number;
QueryForm.UCmd:=1;
OnTerminate:=Term;
Resume;
End;
end;

end.
___________________________________________________________


unit UQuery;

{...}

procedure TFQuery.QryExec(ASQL: String; AProc: Pointer);
Var
Num: Integer;
begin
Num:=GetSQLNum;
AThr[Num]:=AProc;
If Num>iThrCur Then
Begin
AThrHndl[Num]:=CreateQuery(Num,ASQL,FQuery.Handle);
iThrCur:=Num;
End Else
Begin
DMData.TmpSQL:=ASQL;
While Not PostThreadMessage(AThrHndl[Num],PM_THREADCMD,0,0) Do
Sleep(10);
End;

end;

procedure TFQuery.QryTerm;
Var
i: Integer;
begin
For i:=1 To iThrCur Do
Begin
If AThr[i]<>nil Then
PostThreadMessage(AThrHndl[i],PM_ENDTHREAD,0,0);
End;
end;

end.


 
Digitman   (2002-07-25 16:20) [3]

вот это :

procedure TQueryThread.Execute;
begin
end;

ну а где же здесь выборка сообщений из очереди адресованных потоку вызовами PostThreadMessage() ? Где GetMessage() или PeekMessage(), например ? Где собственно код, читающий сообщения из очереди ?


 
Dynamit   (2002-07-25 16:36) [4]

Вообше-то в хелпе пишут, что надо делать эту бадягу только если
траблы!!!

Или у меня и есть траблы?....


 
Digitman   (2002-07-25 16:41) [5]

Это где про "бадягу" и "траблы" пишут ? Процитируй, пожалуйста ...


 
Dynamit   (2002-07-25 16:58) [6]

The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use one of the following methods to handle this situation:

· Call PostThreadMessage. If it fails, call the Sleep function and call PostThreadMessage again. Repeat until PostThreadMessage succeeds.
· Create an event object, then create the thread. Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage. In the thread to which the message will be posted, call PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) to force the system to create the message queue. Set the event, to indicate that the thread is ready to receive posted messages.



The thread to which the message is posted retrieves the message by calling the GetMessage or PeekMessage function. The hwnd member of the returned MSG structure is NULL.


 
Digitman   (2002-07-25 17:06) [7]

Ну и какие "бадяги" да "траблы" ты здесь увидел ?

Вот же , черным по белому написано :

The thread to which the message is posted retrieves the message by calling the GetMessage or PeekMessage function. The hwnd member of the returned MSG structure is NULL

У тебя же ни того ни другого нет в методе Execute. Принимай меры !

PostThreadMessage() всегда дает отказ, если сообщение отправляется в "пустоту", в несуществующую на момент вызова очередь сообщений целевого потока. Первая же из вышеуказанных ф-ций (ни одна из которых у тебя в коде не присутствует) в целевом потоке создаст эту очередь для потока, и последующие вызовы PostThreadMessage() успешно поместят туда свои сообщения целевому потоку.


 
Dynamit   (2002-07-26 09:07) [8]

Тогда не могу понять такой вещи:

У меня будет своя очередь сообщений, в которой я и обрабатываю структуру MSG, а как же тогда функции обработки сообщений - они что не будут работать?? Тогда нафига они нужны???

Вообще тогда все это грустно, т.к. приходилось раньше мне писать проги со своими очередями сообщений (С++, Asm) :(

Дааа....


 
Digitman   (2002-07-26 09:29) [9]

Поясняю простейшим примером , для чего они нужны .

Вот некий цикл обработки соббщений, адресованных потоку.
"Крутится" он где-то в контексте того самого TThread.Execute

while not GetMessage(lpMsg, 0, 0, 0) do
Dispatch(lpMsg.Message);

Вот этот самый виртуальный Dispatch() и диспетчеризует как раз вызовы необходимых, определенных тобой в классе TQueryThread процедур обработки сообщений, если полученные сообщения имеют коды, объявленные тобой в описании тех самых процедур


 
Digitman   (2002-07-26 09:44) [10]

Убери из *.dpr файла на время ма-а-а-аленькую неприметную строчку : Application.Run. И твой вопрос "нафига они нужны ?" прозвучит с тем же гневом))))..

Так вот под этой самой строчкой кроется все тот же цикл - цикл ожидания, приема и автоматической диспетчеризации сообщений. Но - адресованных окнам осн. потока и обрабатываемых, соответственно, в осн.потоке. Разница в том, что касаемо гл.окна приложения и осн.потока Борланд позаботился об автоматической генерации соотв.кода в классе TApplication. Доп. потоки же полностью отданы на откуп тебе - что хочешь, то и делай в них, хочешь - принимай и диспетчеризуй/обрабатывай сам сообщения, не - хочешь - валяй дурака в осн.потоке)..


 
Digitman   (2002-07-26 09:45) [11]

Убери из *.dpr файла на время ма-а-а-аленькую неприметную строчку : Application.Run. И твой вопрос "нафига они нужны ?" прозвучит с тем же гневом))))..

Так вот под этой самой строчкой кроется все тот же цикл - цикл ожидания, приема и автоматической диспетчеризации сообщений. Но - адресованных окнам осн. потока и обрабатываемых, соответственно, в осн.потоке. Разница в том, что касаемо гл.окна приложения и осн.потока Борланд позаботился об автоматической генерации соотв.кода в классе TApplication. Доп. потоки же полностью отданы на откуп тебе - что хочешь, то и делай в них, хочешь - принимай и диспетчеризуй/обрабатывай сам сообщения, не - хочешь - валяй дурака в доп.потоке)..


 
Dynamit   (2002-07-26 12:02) [12]

Вот блин :3( Нифига не выходит - все равно не ловит месг, зараза такая!!!

Может еще чего??


 
Digitman   (2002-07-26 12:39) [13]

Ну, ты внес исправления-то ? Въехал в проблему ? Показывай код тогда)


 
Dynamit   (2002-07-26 13:27) [14]

Дк все то же самое, только вот:
procedure TQueryThread.Execute;
Var
lpmsg: MSG;
begin
Try
with QueryForm do
begin
While (Not Terminated) Do
Begin
If UCmd=1 Then
Begin
{...}
UCmd:=0;
End Else
Begin
While Not GetMessage(lpmsg,0,0,0) Do
Dispatch(lpmsg.Message);
End;
End;
End;
Finally
{...}
End;
end;


 
Digitman   (2002-07-26 13:59) [15]

Ну, я бы сделал так (насколько я понял, чего ты вообще планировал сделать) :



Procedure TQueryThread.PMThreadCmd(var Msg: TMessage);
Begin
{...} // здесь - собственно исполнение некоей команды
End;

procedure TQueryThread.PMEndThread(var Msg: TMessage);
begin
Terminate; // взводим флаг терминирования
end;

procedure TQueryThread.Execute;
Var
lpmsg: MSG;
begin
try
Try
While (Not Terminated) and GetMessage(lpmsg,0,0,0) Do
Dispatch(lpmsg.Message);
Finally
{...}
End;
except
{...}
End;
end;



 
Dynamit   (2002-07-26 14:32) [16]

Нет, так не пойдет - если GetMessage вернет фальш, то цикл закончится, а у меня он только по приходу месги должен терминатиться.

И еще, встретил я тут как-то один глюк:

If (A) And (B) Then
Cmd;

А и В - суть логические выражения.
Дк вот, если А - Истина, то выражение выполниться независимо от В (проверял в отладчике!!). Помогает только скобка:

If ((A) And (B)) Then
Cmd;

Так что... но это не по теме :)


 
Digitman   (2002-07-26 14:53) [17]

>>Нет, так не пойдет - если GetMessage вернет фальш, то цикл
>>закончится, а у меня он только по приходу месги должен
>>терминатиться.

"GetMessage вернет фальш", если кто-либо пошлет потоку сообщение WM_QUIT. Ты его посылаешь ? Нет. А за тебя никто этим не будет заниматься. Так что, в принципе, можешь даже свое PM_ENDTHREAD выкинуть - просто посылай WM_QUIT, и цикл прервется.

а по поводу этого :

>>If (A) And (B) Then
>> Cmd;

>>А и В - суть логические выражения.
>>Дк вот, если А - Истина, то выражение выполниться независимо >>от В (проверял в отладчике!!). Помогает только скобка:

>>If ((A) And (B)) Then
>> Cmd;


Полная чушь. Ты чего-то недоглядел, а пытаешься рушить все каноны булевой алгебры)))



 
Dynamit   (2002-07-26 15:23) [18]

Зря меня в таком обвинять не стоит - не первый год в танке!

Вот как нибудь встретишь - всякое бывает - тогда и поговорим про каноны булевой арифметики (не алгебры).

А по поводу темы разговора - я же не просто так писал - оно действительно не пашет, причем даже при первом запуске!!

Кстати, прога на самом деле порождает по мере необходимости потоки с сокетами к DB400 и удерживает сессии, пока не кирдык!


 
Digitman   (2002-07-26 15:53) [19]

>Dynamit

Значит так, сударь :

Выражение "не пашет" - для меня ничего не значит, кроме поводов усомниться в твоем профессионализме ... Скорее это даже - признак откровенного дилетантства в программинге ... если я не прав - поставь меня на место КОНКРЕТНЫМИ аргументами, а не пустым трепом ! И без жаргона !




 
Dynamit   (2002-07-26 16:25) [20]

Вообще-то странно, что в сети и без жаргона....

Меня как раз и считают отсталым за разговор без жаргона :)

Даллее, спасибо за помощь - она действительно пригодилась - но все же не повод обвинять в дилетанстве человека, не зная его в лицо!!! Я пытался сохранить разговор в духе доброго общения, но каждый раз вместе с помощью получаю подзатыльник - а разве это культурно? Это похуже жаргона - относиться ко всему человечеству как к умственно отсталым!!

Я ухожу в поход на выходные, так что досвиданья, и еще раз спасибо.

Тредсы я конечно добью... Если чего - можно по мылу - я люблю получать письма (без спама)

Не держи зла ;)

Dynamit :o)


 
Digitman   (2002-07-26 16:32) [21]

Черт с ним, с жаргоном. Но "не пашет" - это как минимум несерьезно для человека, воистину пытающегося разобраться до тонкостей в непонимаемом.
Давай говорить конкретными фактами.
Это дает и мне немалый стимул к профессиональному разговору, и тебе - гораздо больший шанс получить точную рекомендацию. Ок ?


 
Dynamit   (2002-07-29 08:59) [22]

Ладно, по порядку:

Я набил в методе Execute основной цикл
While ((Not Terminated) And (GetMessage(lpmsg,0,0,0))) Do
Begin
{...}
End

И при первой же проверке он вылетел по проверке условия и естественно не выполнил свое тело, что привело к зацикливанию программы, т.к. дольнейшие действия определяются приходом сообщений от потока (успешно/неуспешно).
Свойство Terminated не может быть True - некому установить, поэтому все подозрения на GetMessage(lpmsg,0,0,0).

Почему, что и как - я пока не понимаю.

(P.S. Походы - великая вещь!!!)


 
Digitman   (2002-07-29 12:07) [23]

Что ж, будем учиться азам отладки)

Временно не посылай потоку никаких сообщений - поток с таким вот "пустым" циклом после старта должен "зависнуть" на GetMessage(). Если так, однозначно - GetMessage() вызывается корректно и ждет прихода сообщений. Если не ждет и сразу завершается , код возврата сообщит о "неполадках". См. описание GetMessage() в хэлпе


 
Dynamit   (2002-07-29 14:32) [24]

Но из неполадок там всего лишь -1 !?!
Нет, неполадок вроде нет (не уверен). Провел множество экспериментов, а результат таков:
Цикл действительно бесконечен при отсутствии сообщений, но он не выполняет тело цикла (что плохо для программы), а ждет сообщение (хоть какое-нибудь). Т.е. GetMessage() - команда с ожиданием.

Попробовал все вернуть к старой конструкции - когда GetMessage() выполняется по If, но и тут меня постигла неудача.

Также протестировал PeekMessage(), но результата также не добился. Все время получал код возврата - 0. Не знаю, как объяснить мои неудачи, поэтому пишу все, что происходило.

Может еще как нибудь можно поотлаживать, я не знаю...

Сообщение потоку отсылается точно, но не приходит.

И вопрос в догонку: надо ли мне в параметрах Message идентифицировать запрос с помощью WParam или LParam, или поток получает только сообщения, посланные ему не смотря на то, что в параметрах GetMessage в качестве hWnd - 0?


 
Digitman   (2002-07-29 14:54) [25]

hWnd д.б. равным 0 - поток получает только сообщения, адресованные ему и никому другому.

А что говорит GetLastError() ?

Вот это вот :

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle.

наводит на подозрения, что у тебя не доп.поток, а основной ...

GetCurrentThreadId = ThreadId ?


 
Dynamit   (2002-07-29 15:46) [26]

ThreadId - в порядке (т.е. равен GetCurrentThreadId).

Мало того, проверил по шагам выполнение цикла обработки сообщений потока (не в отладчике, а через вывод на экран), получилось, что сообщения приходят, а обработчики сообщений не запускаются :(

Может к методу Dispatch() нужно еще что-то выполнить?

Ошибки нет - т.к. GetMessage() возвращает положительное значение.


 
Digitman   (2002-07-29 16:06) [27]

Как это - "положительное" ??????????

Вот это

-1 !?!

я что ли написал ???????????


 
Dynamit   (2002-07-29 17:08) [28]

Да нет же, я же писал в ответ на это:

> код возврата сообщит о "неполадках". См. описание GetMessage()
> в хэлпе



 
Digitman   (2002-07-30 08:30) [29]

То есть все же "1" возвращает ? Ну, значит, сообщение успешно получено и выбрано из очереди.

поставь брейкпойнт на строчке с Dispatch() и посмотри, чему равно значение поля lpmsg.Message. Это должно быть одно из значений , объявленных тобой в кач-ве констант PM_ENDTHREAD, PM_THREADCMD. Если ни то ни другое, тогда понятно, почему Dispatch() не отрабатывает ожидаемым образом.


 
Dynamit   (2002-07-30 09:00) [30]

Проверил. поле lpmsg.Message=1135
Вывел на экран константу PM_THREADCMD - тоже 1135
????


 
Digitman   (2002-07-30 09:06) [31]

Ну и ? Хочешь сказать, что брейкпойнт в теле обработчика PM_THREADCMD не "ловится" ?


 
Dynamit   (2002-07-30 09:08) [32]

Да !!!


 
Digitman   (2002-07-30 09:15) [33]

Слушай, а как это у тебя поле lpmsg.Message стало кардинального типа ? Это поле д.б. типа запись TMessage, у которой, в свою очередь, есть поле msg - вот оно-то и является кардинальным значением кода сообщения . Давай-ка проверяй все объявления : метод TObject.Dispatch() принимает нетипизированный параметр по ссылке, возможно, ты передаешь ему далеко не структуру TMessage, а что-то другое ... а компилятор "промолчит" - ему по-барабану ..


 
Digitman   (2002-07-30 09:23) [34]

tagMSG = packed record
hwnd: HWND;
message: UINT;
wParam: WPARAM;
lParam: LPARAM;
time: DWORD;
pt: TPoint;
end;
TMsg = tagMSG;
{$EXTERNALSYM MSG}
MSG = tagMSG;

TMessage = packed record
Msg: Cardinal;
case Integer of
0: (
WParam: Longint;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;

About TObject.Dispath :

...
The Message parameter is untyped. The only assumption Dispatch makes about the data in Message is that the first two bytes contain a message ID, that is an integer-that determines which message handler Dispatch calls to handle the message. Although any kind of data can be passed to Dispatch, most TObject descendants expect a message record such as TMessage or a specific message-record type.
...


 
Dynamit   (2002-07-30 09:38) [35]

Я действительно не понимаю здесь что и как объявлять :(
У меня объявлено так:
Var
lpmsg: MSG;

Далее
GetMessage(lpmsg,0,0,0)
и наконец
Dispatch(lpmsg.Message)


 
Digitman   (2002-07-30 11:03) [36]

Структура MSG у тебя взята из Windows.pas ? Тогда - ну хоть убей - это должно работать !
Ты точку останова действительно не "ловишь" в теле процедуры PMThreadCmd() ? Или даже не думал поставить ее туда, ограничившись попыткой пошагово пройти Dispatch() ?

>>"Вывел на экран константу PM_THREADCMD - тоже 1135 "
А чего ее выводить-то ? Ты ж ее сам и определил ! Или не так ?


 
Dynamit   (2002-07-30 11:30) [37]

Структура MSG - не менял, взял как есть.
Ставлю точку останова внутрь PMThreadCmd(), мало того, внутри этой процедуры еще и вывод на экран сообщения (естествено через Synchronize).


> >>"Вывел на экран константу PM_THREADCMD - тоже 1135 "
> А чего ее выводить-то ? Ты ж ее сам и определил ! Или не
> так ?

Я ее определил как
PM_ENDTHREAD=WM_USER+110;
PM_THREADCMD=WM_USER+111;

А т.к. не знаю чему равен WM_USER, пришлось вывести на экран.


 
Digitman   (2002-07-30 12:22) [38]

А на Dispatch(), говоришь, точно отрабатывает брейкпойнт при посылке сообщения ?


Приведи еще раз декларацию и реализацию класса TQueryThread c учетом всех проделанных тобой изменений на последний момент. Бизнес-логику, разумеется, можешь не указывать, заменяя на {...}


 
Dynamit   (2002-07-30 12:59) [39]


> А на Dispatch(), говоришь, точно отрабатывает брейкпойнт
> при посылке сообщения ?


Точно обрабатывает (из кода видно - там еще сообщенице выводится)
Вот наиболее полный код (убрано только совсем лишнее)
--------------
unit UQThread;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, BDE;

type
TFQThread = class(TForm)
QInd: TQuery;
SThr: TSession;
DB1: TDatabase;
Table1: TTable;
private
{ Private declarations }
UCnt, UCmd: LongInt;
UNum: Integer;
UHndl: THandle;
USQL: String;
Function BathMv: LongInt;
procedure CrtRcv;
public
{ Public declarations }
end;

Var
UniqueNumber: Integer;

Function CreateQuery(const Number: Integer; const ASQL: String; AHndl: THandle): THandle;

implementation

Uses UData, UMain;

{$R *.DFM}

Type TQueryThread = class(TThread)
private
QueryForm: TFQThread;
MessageText: string;
procedure DisplayMessage;
procedure SetThreadId;
procedure Term(Sender: TObject);
Procedure SetSQLReady;
Procedure PMEndThread(var Msg: TMessage); message PM_ENDTHREAD;
Procedure PMThreadCmd(var Msg: TMessage); message PM_THREADCMD;
protected
procedure Execute; override;
public
constructor Create(AQueryForm: TFQThread);
end;

constructor TQueryThread.Create(AQueryForm: TFQThread);
begin
QueryForm := AQueryForm;
FreeOnTerminate := True;
inherited Create(True);
end;

procedure TQueryThread.Execute;
Var
lpmsg: MSG;
i: LongBool;
lpMsgBuf: PChar;
begin
SetThreadId;
Try
try
with QueryForm do
begin
SThr.SessionName := Format("A%s%x", [SThr.Name,UNum]);
DB1.SessionName := SThr.SessionName;
DB1.DatabaseName := Format("A%s%x", [DB1.Name,UNum]);
QInd.SessionName := DB1.SessionName;
QInd.DatabaseName := DB1.DatabaseName;

While (Not Terminated) Do
Begin

If UCmd=1 Then
Begin
QInd.SQL.Text:=USQL;
MessageText := USQL;
Synchronize(DisplayMessage);
Table1.TableName:=Format("Tmp\Rcv%x",[UNum]);
Table1.SessionName:=SThr.SessionName;
CrtRcv; // Создание таблицы-приемника
UCnt:=BathMv; // Получение данных
Synchronize(SetSQLReady); //Данные готовы
UCmd:=0;
End Else
Begin
i:=GetMessage(lpmsg,0,0,0);
If Integer(i)<0 Then
Begin
GetMem(lpMsgBuf,1000);
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM,
Nil,GetLastError(), 0,
lpMsgBuf,0,Nil);
MessageText:=String(lpMsgBuf);
Synchronize(DisplayMessage);
FreeMem(lpMsgBuf);
End Else
If Integer(i)>0 Then
Begin
Dispatch(lpmsg.Message);
MessageText:="Message - OK "+#13+IntToStr(Integer(i))+" CMDMSG="+IntToStr(PM_THREADCMD);
Synchronize(DisplayMessage);
End;

End;
End;
End;
except
on E: Exception do
begin
{ Display any error we receive on the status line }
MessageText := Format("Хмм "+QueryForm.QInd.SQL.Text+#13+" %s: %s.", [E.ClassName, E.Message]);
Synchronize(DisplayMessage);
end;
End;
Finally
QueryForm.QInd.Close;
QueryForm.SThr.Active:=False;
QueryForm.DB1.Connected:=False;

End;
end;

procedure TQueryThread.DisplayMessage;
begin
ShowMessage(MessageText);
end;

Procedure TQueryThread.SetSQLReady;
Begin
PostMessage(QueryForm.UHndl,PM_DATAREADY,QueryForm.UNum,QueryForm.UCnt);
End;

procedure TQueryThread.Term(Sender: TObject);
Begin
PostMessage(QueryForm.UHndl,PM_THREADDEAD,QueryForm.UNum,0);
End;

procedure TQueryThread.PMEndThread(var Msg: TMessage);
begin
self.Terminate;
end;

Procedure TQueryThread.PMThreadCmd(var Msg: TMessage);
Begin
MessageText := "Cmd = 1";
Synchronize(DisplayMessage);
QueryForm.QInd.SQL.Text:=DMData.TmpSQL;
QueryForm.UCmd:=1;
End;

Function TFQThread.BathMv: LongInt;
{...}
end;

procedure TFQThread.CrtRcv;
{...}
end;


Function CreateQuery(const Number: Integer; const ASQL: String; AHndl: THandle): THandle;
var
QueryForm: TFQThread;
begin
QueryForm := TFQThread.Create(Application);
QueryForm.Visible:=False;
With TQueryThread.Create(QueryForm) Do
Begin
Result:=ThreadId;
QueryForm.UNum:=Number;
QueryForm.UCmd:=1;
QueryForm.USQL:=ASQL;
QueryForm.UHndl:=AHndl;
OnTerminate:=Term;
Resume;
End;
end;

procedure TQueryThread.SetThreadId; //Это для проверки ThreadId = GetCurrentThreadId
begin
DMData.AThr[QueryForm.UNum]:=GetCurrentThreadId;
end;

end.


 
Digitman   (2002-07-30 13:37) [40]

>>Synchronize(SetSQLReady);

Зачем Synchronize ? С каким неразделяемым ресурсом ты работаешь в SetSQLReady() ? Не вижу ничего, кроме PostMessage()

Ну, это так , к слову ...

Вообще же - ну не вижу я никаких явных плюх ... Если дело до Dispatch() действительно доходит и в момент вызова код сообщения действительно равер константе PM_THREADCMD или PM_ENDTHREAD, то все должно работать !

Хорошо, пробуй на время вот такой (полноэквивалентный) заменитель Dispatch() :


While (Not Terminated) and GetMessage(lpmsg,0,0,0) Do
case lpmsg.Message of
PM_THREADCMD: PMThreadCmd(lpmsg.Message);
PM_ENDTHREAD: Terminate;



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

Форум: "Система";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.008 c
4-32066
kerrik
2002-08-22 22:40
2002.10.10
Как управл. другим прилож., посылая ему комбинации сокр. клавиш?


3-31633
roadrunner
2002-09-13 14:38
2002.10.10
Paradox и DBase


1-31843
runser
2002-09-28 16:16
2002.10.10
Создание компонента


4-32074
oduvan
2002-08-22 10:12
2002.10.10
WinXP ругается, когда удаляю папку (созданную программно)!!!


7-32020
VEG
2002-07-20 19:15
2002.10.10
Работа с LPT портом.





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