Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MsgWaitForMultipleObjects vs Application.Handle

192 views
Skip to first unread message

diego correos

unread,
Jun 22, 2003, 5:17:56 AM6/22/03
to

hello.

i'm creating a thread on a dll. the following is the execute method code:

----------------
procedure THRead.Execute;
var
ret: dword;
HandleList: array [0..1] of THandle;
M: TMsg;
begin
HandleList[0]:=self.Handle;
HandleList[1]:=application.Handle;
While (not(Terminated) and not (Application.Terminated))do
begin
ret:=MsgWaitForMultipleObjects(2, HandleList, false, INFINITE,
(QS_POSTMESSAGE or QS_SENDMESSAGE));
if PeekMessage(M, 0, 0, 0, PM_REMOVE) then
begin
...
end; // end if
end; // end while
end; // end function

----------------

please, see the number 2 in red color.
MsgWaitForMul.... does not wait for anything...... i dont know why,
application.handle is sending
msgs all the time.

and i cant avoid it (put 1), because of i close the app, msgwait still
continious waiting for something (and app
doesnt finish at all)

any idea ?

thanks in advance
diego


Eugene Mayevski

unread,
Jun 22, 2003, 6:32:41 AM6/22/03
to
diego correos wrote:

> HandleList[0]:=self.Handle;
> HandleList[1]:=application.Handle;
> While (not(Terminated) and not (Application.Terminated))do
> begin
> ret:=MsgWaitForMultipleObjects(2, HandleList, false, INFINITE,
> (QS_POSTMESSAGE or QS_SENDMESSAGE));

You can't use window handle with Wait functions. Windows are not kernel
objects.

From MSDN:
===
The MsgWaitForMultipleObjects function can specify handles of any of the
following object types in the pHandles array:

* Change notification
* Console input
* Event
* Job
* Memory resource notification
* Mutex
* Process
* Semaphore
* Thread
* Waitable timer
===

--
Eugene Mayevski
Flexible cross-platform information exchange framework
http://www.msgconnect.com/

Lucian

unread,
Jun 22, 2003, 6:51:26 AM6/22/03
to
HI,

there are some problems with posted code.

1. you should check the return value "ret" for some specific values, and
take appropriate action:
WAIT_FAILED and in your case only when ret = WAIT_OBJECT_0 + 2 you can
process available messages.

2. Application variable used in the dll is different than the one of the
application that loaded the dll. In other words, if project1.exe loads
project2.dll, than project2.Application <> project1.Application

3. what is the thread from dll doing actually? is it waiting for the caller
application to terminate? if that is the case there are better mechanisms
suited for that purpose. Have a look here:
http://www.avdf.com/feb96/jkwin32dll.html
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/dllmain.asp


I found this code on google, might be usefull:

library testdll;

uses
Windows, // DLL_PROCESS_nnn defined in here
SysUtils, Classes;

procedure MyDLLProc(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH: //CALLED WHEN THE DLL IS LOADED
begin
end;

DLL_PROCESS_DETACH: //CALLED WHEN THE DLL IS FREED, IF YOU WANT MULTI
THREADED, LOOK AT DLL_THREAD_DETACH
begin
end;
end;
end;

begin
DLLProc := @MyDLLProc; //THIS SETS THE DLL ENTRY POINT TO THE MyDLLProc.
WHEN EVER THE DLL
//IS LOADED OR UNLOADED, THIS PROC IS CALLED WITH:
//DLL_PROCESS_ATTACH
//DLL_PROCESS_DETACH
//DLL_THREAD_ATTACH
//DLL_THREAD_DETACH

MyDLLProc(DLL_PROCESS_ATTACH); //BECAUSE WE INTERUPTED THE DEFAULT
DLLPROC, WE MUST RECALL OUR PROC
//WITH THE DLL_PROCESS_ATTACH REASON.
end.


diego correos

unread,
Jun 22, 2003, 3:20:44 PM6/22/03
to

hi eugene, first all, thanks for replying.

> You can't use window handle with Wait functions. Windows are not kernel
> objects.

ok, you are right, so, how can i do to detect when app send wm_quit or all
another finalization
messages ?

thanks
diego


diego correos

unread,
Jun 22, 2003, 3:20:47 PM6/22/03
to

hi lucian, first all, thanks for replying to me.

1) its true that i have to verify "ret" value. but it's not a must.
2) what you say about exe.application1.handle <> dll.application2.handle is
a good point.
(and i will take it in mind) but i have tried passing the
exe.application1.handle as a param
of a exported function also. it doesnt work.

3) i'm developing a DLL. the DLL logic must be in a thread. the thread must
catch some user_defined messages that were declarated with
RegisterWindowMessage at the beginning of the dll code.
the thread behaviour is not for waiting app.terminate. but if i dont catch
that message, app cant
finish because there exists some code running in the background (my thread):
i mean, main forms
closes but it doesnt return to delphi's ide: my thread still working.

thanks again
diego

> there are some problems with posted code.
>
> 1. you should check the return value "ret" for some specific values, and
> take appropriate action:
> WAIT_FAILED and in your case only when ret = WAIT_OBJECT_0 + 2 you can
> process available messages.
>
> 2. Application variable used in the dll is different than the one of the
> application that loaded the dll. In other words, if project1.exe loads
> project2.dll, than project2.Application <> project1.Application
>
> 3. what is the thread from dll doing actually? is it waiting for the
caller
> application to terminate? if that is the case there are better mechanisms
> suited for that purpose. Have a look here:
> http://www.avdf.com/feb96/jkwin32dll.html
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas
e/dllmain.asp
>
>
> I found this code on google, might be usefull:
>
> library testdll;
>
> uses
> Windows, // DLL_PROCESS_nnn defined in here
> SysUtils, Classes;
>
> procedure MyDLLProc(Reason: Integer);
> begin
> case Reason of

> DLL_PROCESS_ATTACH: file://CALLED WHEN THE DLL IS LOADED
> begin
> end;
>
> DLL_PROCESS_DETACH: file://CALLED WHEN THE DLL IS FREED, IF YOU WANT


MULTI
> THREADED, LOOK AT DLL_THREAD_DETACH
> begin
> end;
> end;
> end;
>
> begin

> DLLProc := @MyDLLProc; file://THIS SETS THE DLL ENTRY POINT TO THE


MyDLLProc.
> WHEN EVER THE DLL

> file://IS LOADED OR UNLOADED, THIS PROC IS
CALLED WITH:
> file://DLL_PROCESS_ATTACH
> file://DLL_PROCESS_DETACH
> file://DLL_THREAD_ATTACH
> file://DLL_THREAD_DETACH
>
> MyDLLProc(DLL_PROCESS_ATTACH); file://BECAUSE WE INTERUPTED THE DEFAULT


> DLLPROC, WE MUST RECALL OUR PROC

> file://WITH THE DLL_PROCESS_ATTACH
REASON.
> end.
>
>

Eugene Mayevski

unread,
Jun 22, 2003, 3:58:46 PM6/22/03
to
diego correos wrote:

>>You can't use window handle with Wait functions. Windows are not kernel
>>objects.
> ok, you are right, so, how can i do to detect when app send wm_quit or all
> another finalization
> messages ?

There's a method in TApplication, called HookMainWindow. Using it you
can add your handler to the list of handlers. The hook can check for
WM_CLOSE and if there's one, signal an event. And your thread will
check for this event (using one of WaitFor* functions).

diego correos

unread,
Jun 22, 2003, 4:05:24 PM6/22/03
to

hi lucian, about what you say about exe.application.handle <>
dll.application.handle, look what i got:


procedure thread.execute;
begin

application.messagebox('application.handle',pchar(inttostr(fapp_host.handle)
), mb_ok);
application.messagebox('dll handle',pchar(inttostr(application.handle)),
mb_ok);
end

exe.app.handle = 67545645656 (some number)
dll.app.handle = 0.

i can assign dll.application.handle to a param that cames from the exported
function with the
real exe.application.handle, but the problem persist.

reading the delphi's help, i extract:
"When writing a DLL that uses VCL forms, assign the window handle of the
host EXE's main window to the DLL's Application.Handle property. This makes
the DLL's form part of the host application."

any idea ?


Dustin Campbell

unread,
Jun 22, 2003, 6:21:50 PM6/22/03
to
You might have better luck if you discuss this in the proper newsgroup. This
group is for writing Delphi IDE experts. In addition, you should *not* cross
post as this is against Borland's newsgroup guidelines. Try
borland.public.delphi.nativeapi as that newsgroup is for discussion about
the Windows API.

Best Regards,
Dustin Campbell

Rob Kennedy

unread,
Jun 22, 2003, 6:43:40 PM6/22/03
to
diego correos wrote:
> i'm creating a thread on a dll. the following is the execute method code:
>
> ----------------
> procedure THRead.Execute;
> var
> ret: dword;
> HandleList: array [0..1] of THandle;
> M: TMsg;
> begin
> HandleList[0]:=self.Handle;

That is a thread handle. Having a thread wait on its own handle is
completely useless. A thread handle only becomes signaled when it has
terminated. If a thread is terminated, then it cannot possibly be
waiting on its handle. Thus that handle will never satisfy the wait
conditions.

> HandleList[1]:=application.Handle;

That is a window handle. You cannot wait on window handles.

> While (not(Terminated) and not (Application.Terminated))do
> begin
> ret:=MsgWaitForMultipleObjects(2, HandleList, false, INFINITE,
> (QS_POSTMESSAGE or QS_SENDMESSAGE));
> if PeekMessage(M, 0, 0, 0, PM_REMOVE) then
> begin
> ...
> end; // end if
> end; // end while
> end; // end function
>
> ----------------
>
> please, see the number 2 in red color.

Your message arrived in black and white. I see no red. I only see one
"2" in your message, and I'm not sure why you'd point out that character
over any others.

> MsgWaitForMul.... does not wait for anything...... i dont know why,

Well, as I showed above, you haven't given it anything to wait for.

> application.handle is sending
> msgs all the time.

Window handles do not send messages.

> and i cant avoid it (put 1), because of i close the app, msgwait still
> continious waiting for something (and app
> doesnt finish at all)

A moment ago you said MsgWaitForMultipleObjects does not wait for
anything. Now you've said it waits forever. Which is it?

Nevermind. Here's what you can do. When you want your thread to stop,
don't bother with its Terminate method. Instead, post it a wm_Quit
message. That will be you cue to exit the thread's Execute method.

You need to rework your message loop. Right now, it has the potential to
ignore some messages since MsgWaitForMultipleObjects only returns for
*new* messages. So if your thread receives two messages before
MsgWaitForMultipleObjects manages to return, then your call to
PeekMessage will only handle one of them. The remaining message will go
unhandled until your thread receives a third message, and so on.

Instead, you can get rid of the call to MsgWaitForMultipleObjects and
PeekMessage. Replace them with GetMessage. GetMessage will efficiently
wait for a message to arrive. When you're ready to stop the thread, post
it a wm_Quit message and GetMessage will return False.

while GetMessage(M, 0, 0, 0) do begin
// Handle a message
end;

--
Rob

P.S. Your message really should have been sent to the nativeapi
newsgroup, not any of three you sent it to. Please see the guidelines at
http://info.borland.com/newsgroups/.


0 new messages