mauro russo wrote: > what happens when a TThread T object, stopped on > a Synchronize call (having as parameter a TMethod M), > is terminated by the API TerminateThread, executed > in the main thread?
Very bad things. Have you read the documentation for that function? Heed _all_ the advice you've ever read about TerminateThread: Don't call it. > a) Is the method M executed also if T is already terminated? T does not terminate. T is just a plain old Delphi object. T was in possession of an OS thread resource, and that thread suddenly popped out of existence, so T's Handle property is invalid, but there's nothing in T that knows that. > b) what if the TerminateThread is executed in a different thread, but not the > main thread? > Is M executed only if it was already started? TerminateThread doesn't care what thread it's called from. It's just as destructive no matter what. The exact consequences depend on what your program was doing at the time you called TerminateThread. TThread.Synchronize works in two different ways depending on your Delphi version. In older versions, Synchronize calls SendMessage to send a message to a window owned by the main thread. When the main thread calls a message-checking function (including GetMessage, PeekMessage, and SendMessage), the waiting message from Synchronize will be handled. That entails calling the method pointer included in the message's parameters. The thread that called SendMessage is blocked waiting for the receive to grab the message off the queue and finish calling the handler for that message. If the sender thread disappears, I imagine the message remains in the message queue, so the main thread will still get notification that th message is there, and will still handle it. There will just be no thread left blocking waiting for a response. In newer Delphi versions, Synchronize puts method pointers into a queue of their own. It does not use the message queue. It associates an event with the method, notifies the main thread that the queue is non-empty, and then blocks on the event. Once again, if the waiting thread disappears, the main thread won't know it. It will still grab the method off the queue and execute it. It will still signal the event when it's complete. But no one will be left waiting on that event. In either case, the main thread may encounter an error when it tries to determine what method to call. TThread.Synchronize has a TSyncProc record that it fills with the method pointer and other information for the main thread. It allocates that record as a local variable, which means it's on the stack, and then uses a pointer to that variable when it calls SendMessage or puts the pointer on the method queue. Since TerminateThread releases the stack memory associated with the OS thread, the main thread is stuck with an invalid pointer when it finally notices that there's a synchronized method to call. You will still have an object reference for the TThread object. It doesn't become nil when the OS thread is destroyed. The TThread object does not call its OnTerminate event handler, and its Terminated property is not set to True. Trying to free that object will cause it to try to terminate the SO thread gracefully, but of course that won't work because there's no thread there to receive the commands TThread's destructor tries to call. -- Rob

