How to put IDispatch::Invoke to a MFC C++ Thread? - multithreading

How to put the IDispatch::Invoke to a thread and call TerminateThread if it timeouts?
The reason I wanted to do this is because I find that sometimes the Invoke call will go into infinity loop and never return anything and hence the call will just sit there for forever. Hence, I am thinking of putting the Invoke to a thread and terminate the thread when it timeout.
Any advices or references are really appreciated.
Peace

Hi i strongly do not recommend you call TerminateThread for any others things but TerminateThread + IDispatch::Invoke can cause abnormal program termination in good case and more strange program behavior and random crashes in bad one. I think you need chose another way...

Related

Can I call TerminateThread from a VCL thread?

I have found this nice component called TBackgroundWorker. However, people are criticizing it (on SO) because it uses TerminateThread. Here is the "faulty" code:
destructor TBackgroundWorker.Destroy;
begin
if IsWorking then
begin
TerminateThread(fThread.Handle, 0);
Cleanup(True);
raise EBackgroundWorker.CreateFmt(SInvalidExit, [Name]);
end;
inherited Destroy;
end;
For me it seems a valid destructor. Is it? Should I worry?
There is a better solution?
In my opinion, the destructor is valid.
Forcibly terminating a thread is wrong. Also, raising an exception in a destructor may kill the whole application. However, please don't ignore the context.
We talk about a proxy object that wraps a thread. If such a component is running, its destruction is comparable to killing a running thread. The proxy should fail fast and report such a misaction, not manipulate it. Besides, this is a third-party component, which does not know the intent of the application's developer.
I suppose you disagree with me; otherwise, we didn't have this conversation. Let's see what the alternatives are.
Canceling the task and terminating the thread gracefully, no exception message. With this approach, we are guessing the intention of the developer. If the developer has made a mistake, he or she may never know until it is too late. The application would have unexpected behaviors, and it is very complicated to figure out the source of the issue.
Ignoring the running thread and destroying the component anyway, without raising an exception. Seems like turning a deterministic machine into a non-deterministic one. Do we even need to discuss this?
Just raising an exception. Because the thread is still running, the variables and stack trace may hold misleading states, which makes debugging much more difficult.
I believe we all like to discover the bugs in the early stage of development and offer a reliable and stable application to our customers. Should we stop doing that because there is no valid use case for the tool we need to use?
There is always a valid use case for something. If I am wrong, please enlight me.
For me it seems a valid destructor. Is it? Should I worry?
It is a bad destructor code.
First, everything bad you have heard about TerminateThread is true. There is no safe way to terminate thread as it may leave the application in unstable state, and you should never use that function unless you want to immediately close the application, too. And in such cases it is better to just exit the process altogether. See: Calling TerminateThread on a Windows thread when app exits
Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it’s still garbage on the sidewalk
Now the history.
Originally, there was no Terminate­Thread function. The original
designers felt strongly that no such function should exist because
there was no safe way to terminate a thread, and there’s no point
having a function that cannot be called safely. But people screamed
that they needed the Terminate­Thread function, even though it wasn’t
safe, so the operating system designers caved and added the function
because people demanded it. Of course, those people who insisted that
they needed Terminate­Thread now regret having been given it.
It’s one of those “Be careful what you wish for” things.
Additionally, destructor raises an exception, which is something Delphi destructors should never ever do. Raising exceptions in destructor (which are not caught and handled within try..except block) will cause irreparable memory leaks in application.
There is a better solution?
Yes. Since, Cleanup method will call fThread.Free which will wait for thread completion and will perform normal thread shutdown there is no need to call TerminateThread.
Instead of forcing thread termination, it would be better to Cancel the thread and give it time to gracefully terminate itself. This also may require calling WaitFor although pumping Windows messages at that point could interfere with other application code.
destructor TBackgroundWorker.Destroy;
begin
if IsWorking then
begin
Cancel;
// WaitFor;
Cleanup(True);
end;
inherited Destroy;
end;
Ultimately, it is not in the domain of component to handle what happens if the thread is still running during shutdown. If there is a need to handle such scenario and prevent shutdown, then this needs to be handled from outside code.
Generally, I would avoid using this component as generalized solutions can create more problems than they are worth. Waiting for a thread by pumping messages is not the greatest design. It may work well in some circumstances and not in others.
It would be better architecture to rely on TThread.WaitFor function. However, TThread.WaitFor is blocking call, so that behavior may not fit well into TBackgroundWorker architecture and desired behavior.
Note: I didn't fully inspect the code of TBackgroundWorker component so there may be other issues that are not covered in this post.

Reasons for not using SendMessage() to access UI controls from other threads?

I have read that SendMessage() should not be used to access UI controls from other threads, but I'm not sure I know why, the only reason that I can think of is since SendMessage() is a blocking call, then it could cause a deadlock in certain situations.
But is this the only reason not to use it?
Edit: This article talks about the reasons not to use SendMessage() but I don't find it to be very clear (it is intended for .NET).
It is best to keep in mind that the odds that you will write correct code are not very good. And the generic advice is don't do it! It is never necessary, the UI thread of a GUI program in Windows was entirely structured to make it simple to allow code that runs on another thread or inside a process affect the UI of the program. The point of the message loop, the universal solution to the producer-consumer problem. PostMessage() is your weapon to take advantage of it.
Before you forge ahead anyway, start by thinking about a simple problem that's very hard to solve when you use SendMessage. How do you close a window safely and correctly?
Given is that the exact moment in time that you need to close the window is entirely unpredictable and completely out of sync with the execution of your worker thread. It is the user that closes it, or asks the UI thread to terminate, you need to make sure that the thread has exited and stops calling SendMessage before you can actually close the window.
The intuitive way to do this is to signal an event in your WM_CLOSE message handler, asking the thread to stop. And wait for it to complete, then the window can close. Intuitive, but it does not work, it will deadlock your program. Sometimes, not always, very hard to debug. Goes wrong when the thread cannot check the event because it is stuck in the SendMessage call. Which cannot complete since the UI thread is waiting for the thread to exit. The worker thread cannot continue and the UI thread cannot continue. A "deadly embrace", your program will hang and needs to be killed forcibly. Deadlock is a standard threading bug.
You'll shout, "I'll use SendMessageTimeout!" But what do you pass for the uTimeout argument and how do you interpret an ERROR_TIMEOUT error? It is pretty common for a UI thread to go catatonic for a while, surely you've seen the "ghost window" before, the one that shows 'Not Responding` in the title bar. So an ERROR_TIMEOUT does not reliably indicate that the UI thread is trying to shut down unless you make uTimeout very large. At least 10 seconds. That kinda works, getting the occasional 10 second hang at exit is however not very pretty.
Solve this kind of problem for all the messages, not just WM_CLOSE. WM_PAINT ought to be next, another one that's very, very hard to solve cleanly. Your worker thread asks to update the display a millisecond before the UI thread calls EndPaint(). And thus never displays the update, it simply gets lost. A threading race, another standard threading bug.
The third classic threading bug is a fire-hose problem. Happens when your worker thread produces results faster than the UI thread can handle them. Very common, UI updates are pretty expensive. Easy to detect, very hard to solve and unpredictable when it occurs. Easy to detect because your UI will freeze, the UI thread burns 100% core trying to keep up with the message rate. It doesn't get around to its low-priority tasks anymore. Like painting. Goes wrong both when you use SendMessage or PostMessage. In the latter case you'll fill the message queue up to capacity. It starts failing after it contains 10000 unprocessed messages.
Long story short, yes, SendMessage() is thread-safe. But thread-safety is not a transitive property, it doesn't automatically make your own code thread-safe. You still suffer from all the things that can go wrong when you use threads. Deadlocks, races, fire-hosing. Fear the threading beast.

Does TTimer.OnTimer causes a worker thread to synchronize with a main thread?

I have to work with legacy code. This code has a TTimer created in a main thread.
In OnTimer event the timer is checking periodically a state of some data in the worker thread.
pseudocode:
procedure MainForm.OnTimer(Sender: TObject);
begin
if WorkerThread.Data.State = full then
begin
WorkerThread.Free; //This freezes GUI.
end else
//Do something else.
end;
The problem is that I want to do some background operation when the WorkerThread is terminating. To avoid synchronization I've overriden DoTerminate method. However in this particular case, this is not helping and my GUI becomes frozen until the DoTerminate finishes.
Can I somehow avoid the freeze?
Thanks.
There's not enough code here to say anything with any certainty. However, calling Free on a thread results in a call to Terminate followed by a WaitFor. It's quite plausible that the wait is not returning which would be consistent with the frozen UI.
This is truly backwards. In any decent threading scheme, your thread will be notifying your gui-thread about a condition like .Data.State = full. You gui-thread or main-thread will then take appropriate action. One thing i am certain about is that WorkerThread.Free must be wrong. Trying to free a thread that's apparently blocked for whatever reason, is guaranteed to fail. Thread.Terminate will also fail if the thread is blocked, so no help there either.
Having a Timer monitor the status of a thread is never right. I never use the words always and never, but... I'll repeat: Having a Timer monitor the status of a thread is never right. Never ever. Don't even think about it.
turin

terminate a thread in delphi

How can I terminate a thread in a proper way?
When the thread finishes, it is still in memory. I'm using Delphi 2010 (Update 5).
The way I usually describe the issues of thread termination is to stress co-operation. You should not terminate a thread. Instead you should notify the thread that you want it to terminate. You then politely wait until it has terminated.
The reasons for this are manifest. Only the thread knows how to terminate itself. Only the thread knows what locks it holds, what resources it needs to free etc.
The same arguments apply if you wish to pause or suspend a thread's execution. You should ask to it do so and then let the thread find a convenient moment when it is safe to do so.
With a Delphi TThread the standard way to request termination is to call Thread.Terminate. This does nothing more than to set a flag in the thread object. That is the request. The response is initiated by the thread code inside TThread.Execute. That should regularly check the value of its Terminated property. When that is found to be true, it should exit from the function. Naturally any tidy up (release locks, return resources etc.) should be performed before calling exit.
How exactly do you terminate a thread? If you just set Terminate, this is just a flag checked inside of the thread. If you need to terminate thread of execution (and not signal a TThread object that it needs to finish), you can use TerminateThread WinAPI function. But you should notice that this leads to resource leaks (as written in the comments in documentation for TerminateThread).
that depends on what you want to accomplish with that thread. you should provide more details about what you want to do, before we can help you.
here you have a very good tutorial on how to work with threads in Delphi:
http://www.eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/Ch1.html
http://docwiki.embarcadero.com/RADStudio/en/Writing_multi-threaded_applications_Index

How to stop long executing threads gracefully?

I have a threading problem with Delphi. I guess this is common in other languages too. I have a long process which I do in a thread, that fills a list in main window. But if some parameters change in the mean time, then I should stop current executing thread and start from the beginning. Delphi suggests terminating a thread by setting Terminated:=true and checking for this variable's value in the thread. However my problem is this, the long executing part is buried in a library call and in this call I cannot check for the Terminated variable. Therefore I had to wait for this library call to finish, which affects the whole program.
What is the preferred way to do in this case? Can I kill the thread immediately?
The preferred way is to modify the code so that it doesn't block without checking for cancellation.
Since you can't modify the code, you can't do that; you either have to live with the background operation (but you can disassociate it from any UI, so that its completion will be ignored); or alternatively, you can try terminating it (TerminateThread API will rudely terminate any thread given its handle). Termination isn't clean, though, like Rob says, any locks held by the thread will be abandoned, and any cross-thread state protected by such locks may be in a corrupted state.
Can you consider calling the function in a separate executable? Perhaps using RPC (pipes, TCP, rather than shared memory owing to same lock problem), so that you can terminate a process rather than terminating a thread? Process isolation will give you a good deal more protection. So long as you aren't relying on cross-process named things like mutexes, it should be far safer than killing a thread.
The threads need to co-operate to achieve a graceful shutdown. I am not sure if Delphi offers a mechanism to abort another thread, but such mechanisms are available in .NET and Java, but should be considered an option of last resort, and the state of the application is indeterminate after they have been used.
If you can kill a thread at an arbitrary point, then you may kill it while it is holding a lock in the memory allocator (for example). This will leave your program open to hanging when your main thread next needs to access that lock.
If you can't modify the code to check for termination, then just set its priority really low, and ignore it when it returns.
I wrote this in reply to a similar question:
I use an exception-based technique
that's worked pretty well for me in a
number of Win32 applications.
To terminate a thread, I use
QueueUserAPC to queue a call to a
function which throws an exception.
However, the exception that's thrown
isn't derived from the type
"Exception", so will only be caught by
my thread's wrapper procedure.
I've used this with C++Builder apps very successfully. I'm not aware of all the subtleties of Delphi vs C++ exception handling, but I'd expect it could easily be modified to work.

Resources