Paul
> I use the RegisterWindowMessage function to communicate between a
> service and a thread. When a destop changes, all threads have to
> switch to the new input desktop, but one of them fails. This thread
> uses the RegisterWindowMessage() function to communicate with the
> service. It's not clear to me (from msdn) if RegisterWindowMessage
> creates a hidden window or not.
No, it just creates an atom in the Windows global atom table. But you
should not use Windows messages for communication with a service, since
that does not work across desktops. On Vista, for example, a GUI app
would not be able to communicate with a service this way.
--
Peter Below (TeamB)
Don't be a vampire (http://slash7.com/pages/vampires),
use the newsgroup archives :
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
I know, but all /real/ user interface is handled thru a program that is
started when a user is logged on.
It's connected with the main service thru a pipe.
The thread doesn't read anything directly, but thru a driver.
I used the window messages so that it's compatible with another version of
the application that doesn't have to switch between desktops.
Seems I should rewrite the thread ...
Paul
> I know, but all /real/ user interface is handled thru a program
> that is started when a user is logged on.
Which is perfectly fine. But the communication between that program
and the service should not be based on window messages at all. Use
other IPC mechanisms instead, such as named pipes, mailslots, or
TCP/IP sockets. As for communications inside the service amongst its
internal threads, there is no need for RegisterWindowMessage() at all.
Hard-code the message IDs instead, in the WM_APP range.
Gambit
Remy,
The IPC hasn't been the problem.
In case you haven't noticed, the communication between that program and the
main service goes through a pipe.
There are a few threads that needs to switch to the input desktop and one of
them won't do it.
I know there are a few components that use a handle (like a timer), but they
are destroyed before switching to the new desktop and recreated afterwards.
But there is still something that's blocking the switch.
Paul
> The IPC hasn't been the problem. In case you haven't noticed, the
> communication between that program and the main service goes
> through a pipe. There are a few threads that needs to switch to the
> input desktop and one of them won't do it.
Like I said before, your internal threads have no reason to call
RegisterWindowMessage() in the first place. That is why Microsoft set
asside a specific range of messages that an application can use for
its private use. RegisterWindowMessages() is primarily used for when
multiple processes have to send messages to each other. That is not
the case here.
> I know there are a few components that use a handle (like a timer),
> but they are destroyed before switching to the new desktop and
> recreated afterwards.
You shouldn't be using a TTimer in a service to begin with. It is not
a thread-safe component (none of the UI components are). Use a
multimedia timer instead, via the timeSetEvent() function. It is a
threaded timer. If you must continue using TTimer, then keep it in
the TService's main thread only, as that thread has no business moving
between desktops anyway.
Gambit
I didn't change the communication to be compatible with another version, but
I can use a pipe.
I can change (and probably need according to Peter) the IPC, but this cannot
be the reason why the thread won't switch between desktops.
> You shouldn't be using a TTimer in a service to begin with. It is not
> a thread-safe component (none of the UI components are). Use a
> multimedia timer instead, via the timeSetEvent() function. It is a
> threaded timer. If you must continue using TTimer, then keep it in
> the TService's main thread only, as that thread has no business moving
> between desktops anyway.
Well, I disagree on this.
I've used timers in threads for years, and never had a single problem with a
timer, you only need a message loop,
and it can't be the problem with desktop switching. It's destroyed before
switching anyway.
Paul
> I didn't change the communication to be compatible with another
> version, but I can use a pipe. I can change (and probably need
> according to Peter) the IPC, but this cannot be the reason why the
> thread won't switch between desktops.
If the thread already owns a window (which is tied to a desktop) it
cannot switch to another desktop, as far as I know. A TTimer creates a
helper window behind your back...
> A TTimer creates a helper window behind your back...
And like I said earlier, that is not thread-safe anyway. Creating
that window uses global resources that the VCL does not protect from
multi-threaded access.
Gambit
> If the thread already owns a window (which is tied to a desktop) it
> cannot switch to another desktop, as far as I know. A TTimer creates a
> helper window behind your back...
I know, and it's also destroyed before switching.
Just for testing, I changed the code and the whole thread is restarted and
recreated when the desktop changes.
The thread switches to the input desktop in it's execute before creating all
objects (and RegisterWindowMessage).
This works, so appearantly, RegisterWindowMessage does work across desktops.
But this is not the way I like it.
I also make a log of the desktop handles of 2 threads that have to 'follow'
the input desktop.
What confuses me is that both threads start in the same desktop (usually 40
on my PC), but after a desktop change, the new desktops are different in
both threads.
Paul
I know the VCL is not threadsafe, but a hidden window (not a form) can be
used without problems in a thread.
That's what a TTimer does.
Just the same as you van use bitmaps in thread's also as long as you lock
it's canvas
Paul
"Remy Lebeau (TeamB)" <no....@no.spam.com> schreef in bericht
news:45bbfba9$1...@newsgroups.borland.com...
> What you are saying here that you cannot use a hidden window in a
thread.
That is not what I said. Of course you can use a window in a thread -
in general. I was referring to the special fact of TTimer's hidden
window. TTimer uses AllocateHwnd() to create its window.
AllocateHWnd() in turn uses MakeObjectInstance() (as all VCL windows
components do) to create a proxy stub that allows a class method to
operate as an OS window procedure. MakeObjectInstance() allocates and
accesses shared resources that are not thread-safe. If you are not
careful, you can really mess things up for the VCL's window handlers.
If you really want to use a thread-specific window that is
thread-safe, you should use the Win32 API CreateWindow() function
directly.
> I know the VCL is not threadsafe, but a hidden window (not a form)
> can be used without problems in a thread. That's what a TTimer does.
If TTimer were using CreateWindow() by itself, then there would be no
problem. But it does more than that, and that is where problems begin
to appear.
Gambit
not only I use AllocHwnd, I've seen many programmers using it.
My most used program worldwide uses it and it's downloaded/installed a few
hundred times a day for almost 3 years.
Not a single one has complained it didn't work.
I don't what you need to prove it does or does not work, but for me it
proofs its working perfect.
Paul
"Remy Lebeau (TeamB)" <no....@no.spam.com> schreef in bericht
news:45bc875e$1...@newsgroups.borland.com...
That doesn't mean it worked. That just means no one told you about it,
or that when someone told you, you didn't recognize that it was a
threading issue with the timer.
> I don't what you need to prove it does or does not work, but for me it
> proofs its working perfect.
That's the thing about threads. No amount of testing will prove it's
correct. None. Because every time you test, it might just be a
coincidence that the race condition did not manifest itself -- every
time it was important, the right thread won the race. That only means
you're lucky, which is a hindrance in our line of work.
That doesn't mean your program is correct. If there is a race condition,
then your program has a bug. The wrong thread might win the race
someday. A change to something else in your program -- file I/O, perhaps
-- or a change to the way the operating system schedules threads to run,
could affect the order in which the instructions in your threads get run.
There are other ways of making code run periodically. You don't have to
use a TTimer. You can use a plain windows timer, or a multimedia timer,
or an ITimer, or a waitable timer. Just because TTimer is easy doesn't
change the fact that it's the wrong choice.
--
Rob
> You can use a plain windows timer
Although TTimer wraps a "plain windows timer", it uses an HWND to
receive the timer message. Windows timers can also use callback
functions instead without the use of a HWND at all. All you need is
an active message queue, which you need in order for TTimer to work
anyway.
Gambit
Right. As I understant it, the problem with TTimer isn't that it uses a
window. The problem is how it gets that window -- AllocateHWnd and
MakeObjectInstance. If you create a window some other way, then there's
no problem with using a regular Windows timer.
--
Rob