+10  A: 

The VCL (and parts of the RTL) is not thread-safe, so you cannot move components around from a thread. You have several options:

  • Use a TTimer component. You don't need a thread and the timer's event handler will be executed in the context of the main thread. The timer was designed exactly for things like that.
  • Synchronize all VCL related stuff in the thread. TThread provides a static method Synchronize that does exactly that.
  • Send messages from the thread to the form using SendMessage or PostMessage and handle this message in the form.

You might also consider to use the TThread wrapper class instead of using BeginThread and EndThreadexplicitly when working with threads.

Smasher
The VCL is designed to be manipulated from one thread only, true, but most of the RTL is thread-safe - depending on what definition one uses. For example, it certainly isn't the case that you must serialize all RTL function calls; the memory manager is thread-safe; almost all routines are thread-safe, because very few manipulate shared state; but I/O using Writeln etc. isn't when targeting the same file (or console).
Barry Kelly
You're right of course. It would indeed be a pain if the whole RTL would be unsafe to use from multiple threads. I edited that part.
Smasher
A: 

Using Synchronize() would be the down and dirty method of synchronizing the procedures that move the buttons. Synchronize() forces the method to be run in the main VCL thread. They'll block each other, so only one button can move at a time. This will avoid encountering non-thread safe code in the VCL.

I couldn't recreate the issue of the form freezing though, so I'm not sure that is your issue. You may wish to look elsewhere.

Marcus Adams
I do not agree. The VCL thread simply does nothing since everything happens within the two threads. If using `Synchronize` this might indeed be a problem. `Application.ProcessMessages` should not be necessary here.
Smasher
The last sentence should be removed, it makes no sense at all. Calling `CloseHandle()` immediately has no negative effect whatsoever, while not calling it would leak system handles. There's no effect on thread *execution*. Also, `Synchronize()` is much more about scheduling code to run in the context of the VCL thread than about synchronizing the code execution. There's other ways to do the latter (like critical sections), but using them instead wouldn't fix the problem.
mghie
A: 
isa
This is not an answer to your question. @Smasher correctly answered why stuff in your question doesn't work, and why you shouldn't do anything like it, at all. Finding corner cases that do work does not alter the facts. The progress bar code works because it is just `SendMessage(Handle, PBM_SETPOS, Value, 0)` internally, so it's serialized via the message queue. Just accept Smashers answer already...
mghie