Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Mar : Re: TIdTCPServer - threads, global data
| Subject: | Re: TIdTCPServer - threads, global data |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Wed, 15 Mar 2006 17:29:10 |
"Martin James" <mjames_falcon@dial.pipex.com> wrote in message
news:4418691f@newsgroups.borland.com...
> Remy has raised the annoying point that posting/sending directly
> to form handles is unsafe.
Sending/posting by itself is perfectly safe. The way that Mathjis is
retreiving the HWND being sent/posted to, on the other hand, is not safe.
That is what I was commenting on earlier. The TWinControl.Handle property
is not thread-safe.
> Windows crappy code has to recreate Windows for some operations,
> (eg. change BidMode) because..well.. it's crappy.
Actually, it is Borland's own code, not Microsoft's, that requires that.
Microsoft allows the styles of a window to be changed dynamically without
recreating the HWND. But Borland does not do that, mainly because it wants
to be able to apply multiple styles from a single operation. Even when one
style is changing, Borland usually recreates the HWND so that all styles are
reapplied in bulk, so that a single piece of code can handle them all in a
single location.
> PostMessage also avoids the twin horrors of:
>
> 'TThread.synchronize' (sucks)
> 'TThread.waitFor' (sucks bad)
There is nothing wrong with those methods (other than the bug that WaitFor()
has under D6+ when FreeOnTerminate is True)
PostMessage(), on the other hand, is not error-free, either. If a message
fails to be posted, or the message queue does not remove all pending
messages, then you have memory leaks.
> CM_OBJECTRX=$8FF0;
I highly recomend using RegisterWindowMessage() instead of a constant.
Also, you are not validating that the received message is genuine before
using the message's parameters.
> ThreadPostWindowClass: TWndClass = (
The VCL has an AllocateHWnd() function that handles those details for you.
> ThreadPostWindow:=CreateWindow(...
queueObjectToMainThread() is not checking whether CreateWindow() actually
succeeded or not.
> DestroyWindow(ThreadPostWindow);
You are not setting ThreadPostWindow back to nil, in case another unit calls
queueObjectToMainThread() after the unit has been finalized.
Also, the problem with using a dedicated unit to manage the queue is that
you have to ensure that it gets finalized properly before any threads are
created, and that all threads are fully terminated before the unit is
finalized.
Gambit