![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Messages & TThread [D6, Win2k]
Dynamit © (2002-07-25 14:01:00)Уважаемые Мастера, помогите: не обрабатываются сообщения, посланные потоку (ThreadID) командой PostThreadMessage.
Вот как тут не плакать :(
Digitman (2002-07-26 09:45:00) [41]Убери из *.dpr файла на время ма-а-а-аленькую неприметную строчку : Application.Run. И твой вопрос "нафига они нужны ?" прозвучит с тем же гневом))))..
Так вот под этой самой строчкой кроется все тот же цикл - цикл ожидания, приема и автоматической диспетчеризации сообщений. Но - адресованных окнам осн. потока и обрабатываемых, соответственно, в осн.потоке. Разница в том, что касаемо гл.окна приложения и осн.потока Борланд позаботился об автоматической генерации соотв.кода в классе TApplication. Доп. потоки же полностью отданы на откуп тебе - что хочешь, то и делай в них, хочешь - принимай и диспетчеризуй/обрабатывай сам сообщения, не - хочешь - валяй дурака в доп.потоке)..
Digitman (2002-07-26 09:44:00) [42]Убери из *.dpr файла на время ма-а-а-аленькую неприметную строчку : Application.Run. И твой вопрос "нафига они нужны ?" прозвучит с тем же гневом))))..
Так вот под этой самой строчкой кроется все тот же цикл - цикл ожидания, приема и автоматической диспетчеризации сообщений. Но - адресованных окнам осн. потока и обрабатываемых, соответственно, в осн.потоке. Разница в том, что касаемо гл.окна приложения и осн.потока Борланд позаботился об автоматической генерации соотв.кода в классе TApplication. Доп. потоки же полностью отданы на откуп тебе - что хочешь, то и делай в них, хочешь - принимай и диспетчеризуй/обрабатывай сам сообщения, не - хочешь - валяй дурака в осн.потоке)..
Digitman (2002-07-26 09:29:00) [43]Поясняю простейшим примером , для чего они нужны .
Вот некий цикл обработки соббщений, адресованных потоку.
"Крутится" он где-то в контексте того самого TThread.Execute
while not GetMessage(lpMsg, 0, 0, 0) do
Dispatch(lpMsg.Message);
Вот этот самый виртуальный Dispatch() и диспетчеризует как раз вызовы необходимых, определенных тобой в классе TQueryThread процедур обработки сообщений, если полученные сообщения имеют коды, объявленные тобой в описании тех самых процедур
Dynamit (2002-07-26 09:07:00) [44]Тогда не могу понять такой вещи:
У меня будет своя очередь сообщений, в которой я и обрабатываю структуру MSG, а как же тогда функции обработки сообщений - они что не будут работать?? Тогда нафига они нужны???
Вообще тогда все это грустно, т.к. приходилось раньше мне писать проги со своими очередями сообщений (С++, Asm) :(
Дааа....
Digitman (2002-07-25 17:06:00) [45]Ну и какие "бадяги" да "траблы" ты здесь увидел ?
Вот же , черным по белому написано :
The threadto 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-25 16:58:00) [46]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 16:41:00) [47]Это где про "бадягу" и "траблы" пишут ? Процитируй, пожалуйста ...
Dynamit (2002-07-25 16:36:00) [48]Вообше-то в хелпе пишут, что надо делать эту бадягу только если
траблы!!!
Или у меня и есть траблы?....
Digitman (2002-07-25 16:20:00) [49]вот это :
procedure TQueryThread.Execute;
begin
end;
ну а где же здесь выборка сообщений из очереди адресованных потоку вызовами PostThreadMessage() ? Где GetMessage() или PeekMessage(), например ? Где собственно код, читающий сообщения из очереди ?
Dynamit (2002-07-25 16:07:00) [50]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 15:17:00) [51]код-то где ?