Synchronize() hangs up the thread - multithreading

I'm writing a dll library in Delphi with multiple threads created by it. Let me describe the problem step by step. I'm sorry for a lengthy description in advance :-(.
Let's forget about the library for a while. I created a windows application that is going to present views from several cameras. I created a window which is meant to show the view from a single camera and it contains a TImage control. There is a thread (a TThread descendant) that downloads the current image from the camera every couple of milliseconds and assigns it to the TImage control of that window (using the Synchronize() method). The application creates several instances of that window on startup (with a separate thread for each of them), so you can see the live view from several cameras at once. What's more, all those viewing windows are parented by the main application window, so they appear within it.
Everything worked fine until I decided to put those two windows into a dll library. I just found it necessary for some reasons, but they are not important now. So I created a new dll library, added the existing main window and the camera-view window to the project and exported a function that creates and returns an instance of the main window. When the main window is created, it creates several camera-view windows, making itself their parent.
Then, for testing purposes, I created an app that imports the above mentioned dll function from the library and calls it at startup to get an instance of the main window; then just shows it on the screen (in a non-modal state).
When I started the app it came out that I couldn't get a single image from any camera then. When I debugged it, I noticed that when the thread calls the Synchronize() method, it hangs forever. It didn't happen before putting both those windows into a dll.
And this is my problem. To be honest, this is my first approach to libraries I have had to get through many other problems so far. You might wonder why I use windows instead of frames... So whenever I created an instance of a TFrame in a dll, I would get an exception saying "the control xxx does not have a parent window". I did not know what to do about that so I used windows instead :-(.
Could you please tell me what to do with the synchronization problem? The main thread does not seem to be blocked in any way when the application is started for it accepts clicking buttons etc. What is the problem then?
Please, help!
Thank you in advance!!

When you call TThread.Synchronize the thread and method pointer are added to a global SyncList: TList in Classes.pas. In the main exe's TApplication.Idle routine calls CheckSynchronize, which checks the SyncList, but it's going to check the version in the exe instead of the one in the DLL. End result, your synchronized methods are never called.
The easiest fix would be to switch from DLLs to packages, which would eliminate the duplicate SyncList.
Another approach would be to override the exe's Application.OnIdle callback, and call your DLL's CheckSynchronize manually. You would need some help from the application for that though, since your DLL will have an Application object too, and that one won't work.

It's a bad idea to use Synchronize, because it tends to lead to race conditions like this. I don't know what's going on specifically in your code--it's hard to tell without seeing any code--but this sort of issue is pretty common actually.
Inter-thread communication is better done with a queue. If you've got the latest version, Delphi XE, there's a TThreadedQueue<T> class in Generics.Collections that's ideal for this sort of thing. Pass 0 to the PopTimeout param in the constructor, have your camera threads push images, and have your main thread poll the queues with the third PopItem overload, like so:
var
CurrentItem: TImage;
begin
if ThreadQueue.PopItem(CurrentItem) = wrSignaled then
UpdateImage(CurrentItem); //or however you do it
end;
(If there's nothing in the queue, PopItem will return wrTimeout instead.)
If you don't have Delphi XE, you'll need to build your own threadsafe queue, or find one from a third party source, such as Primoz Gabrielcic's OmniThreadLibrary.

I found two ways to solve Synchronize() hanging up the thread (in Delphi 7):
Place a TTimer on the DLL form and have its OnTimer event call CheckSynchronize();
procedure TPluginForm.Timer1Timer(Sender: TObject);
begin
CheckSynchronize;
end;
Add this module to the uses section of the DLL form

Related

Synchronize () DLL freezes without errors and crashes

I built a modular program consisting of several programs (exe), and in some cases these modules are also in DLL. There are about 6 modules.
All of these modules used functions of a Thread. This thread does not use visual components, what it does is basically analyze huge files (> 1GB).
To improve the efficiency and organization, extract all the code relating to this file analysis, which is used by each of the modules. This facilitates updating and find error.
The threads worked normally before, no code change, except as necessary to adapt them to the DLL project.
Now, when I run the procedures of Thread, everything functions normally except the synchronize () method, which freezes without making errors or lock the main program.
The synchronize () method is used because the threads are created entirely within the DLL. Therefore, the main program is called a procedure DLL, which creates and runs the thread, without any intervention by the main program.
For this procedure are passed several parameters, one of them is a type "pointer to procedure" ^procedure, who is using it as an event, fired by the thread through the synchronize () periodically, ensuring that during the performance, which lasted more than one hour in most sometimes, if track progress, see errors errors among others.
I searched on google but did not find information except someone saying that possibly the synchronize () method is waiting for the main process that is not responding for unknown reasons.
Note: The main program and the window does not lock or freeze; only the thread that does not call / run procedure provided to synchronize (); I confirmed it!
Added
Nota2: I want to avoid as much use PostMessage () or similar, because it forces me to include LCL, which makes the DLL file up from the current 300K to 2MB (in release mode). Apart from that there are reports that its operation is not good as expected.
That is because you have two complete instances of everything (RTL,LCL etc). One set in the DLL, one set in the EXE. Both code and data.
You are probably calling the synchronize of the DLL, which schedules it for the LCL loop in the DLL which does nothing, since all work is done in the EXE.
This will be very hard to fix, basically you need packages for this. Partially also because the thread involvement will further complicate it because of threadvariables (Thread local storage) that is set up potentially differently for DLL and EXE threads.
For this one needs packages which is only in its initial stages and solves this by having only one copy of everything. See the link for a deeper treatise.

OpenFileDialoug Current Thread Must Be STA before OLE calls made

Can someone explain to me what this error I'm seeing is?
Current thread must be set to single thread apartment (STA) mode before OLE calls can be made.
Specifically, I'm trying to open the SaveFileDialog/OpenFileDialog within C++/CLI on a form.
SaveFileDialog^ saveFileDialog1 = gcnew SaveFileDialog;
saveFileDialog1->ShowDialog();
if (saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
s = saveFileDialog1->OpenFile();
}
s->Close();
}
The error that is throwing is
An unhandled exception of type 'System.Threading.ThreadStateException' occurred in System.Windows.Forms.dll
Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.
I'm not really familiar with what this error is saying. I know just a bit about threading, but I'm not sure how threading would be an issue here. I've seen some people reference things like STAThread without providing a clear explanation as to what it does, and Microsoft's documentation makes no mention of having this exception thrown when calling SaveFileDialog/OpenFileDialog, or how to handle it.
Thanks!
When you use OpenFileDialog then a lot of code gets loaded into your process. Not just the operating system component that implements the dialog but also shell extensions. Plugins that programmers write to add functionality to Windows Explorer. They work in that dialog as well. There are many, one you are surely familiar with is the extension that makes a .zip file look like a folder.
One thing Microsoft did when they designed the plug-in interface is to not force an extension to be thread-safe. Because that is very hard to do and often a major source of bugs. They made the promise that the thread that creates the plugin instance is also the thread on which any call to the plugin is made. Thus ensuring that the plugin is always used in a thread-safe manner.
That however requires a little help from you. You have to make a promise that your thread, the one that calls OpenFileDialog::Show(), observes the requirements of a single-threaded apartment. STA for short. You make the promise with the [STAThread] attribute on your program's Main() entrypoint. Or if it is a thread that you created yourself then by calling Thread::SetApartmentState() before you start it.
That's just a promise however, you also have to implement what you promised. Takes two things, you promise to never block the thread and you promise to pump a message loop. Application::Run() in a .NET program. The never-block promise ensures that you won't cause deadlock. And the message loop promise says that you implement a solution to the producer-consumer problem.
This should never be a problem, it is very unclear how this got fumbled in your project. Another implicit requirement for a dialog is that it must have an owner. Another window on which it can be on top of. If it doesn't have one then there are very high odds that the user never sees the dialog. Covered by another program's window, the user can only ever find it back by accident. When you create windows then you always also must call Application::Run() so the windows can respond to user input. Use the boilerplate code in a C++/CLI app so this is done correctly.

Why the window of my vb6 application stalls when calling a function written in C?

I'm using 3.9.7 cURL library to download files from the internet, so I created a dynamic bibioteca of viculo. dll written in C using VC + + 6.0 the problem is that when either I call my function from within my vb6 application window locks and unlocks only after you have downloaded the file how do I solve this problem?
The problem is that when you call the function from your DLL, it "blocks" your app's execution until it gets finished. Basically, execution goes from the piece of code that makes the function call, to the code inside of the function call, and then only comes back to the next line after the function call after the code inside of the function has finished running. In fact, that's how all function calls work. You can see this for yourself by single-stepping through your code in the VB 6 development environment.
You don't normally notice this because the code inside of a function being called doesn't take very long to execute before control is returned to the caller. But in this case, since the function you're calling from the DLL is doing a lot of processing, it takes a while to execute, so it "blocks" the execution of your application's code for quite a while.
This is a good general explanation for the reason why your application window appears to be frozen. A bit more technically, it's because the message pump that is responsible for processing user interaction with on-screen elements is not running (it's part of your code that has been temporarily suspended until the function that you called finishes processing). This is a bit more difficult for a VB programmer to appreciate, since none of this nitty-gritty stuff is exposed in the world of VB. It's all happening behind the scenes, just like it is in a C program, but you don't normally have to deal with any of it. Occasionally, though, the abstraction leaks, and the nitty-gritty rears its ugly head. This is one of those cases.
The correct solution to this general problem, as others have hinted at, is to run lengthy operations on a background thread. This leaves your main thread (right now, the only one you have, the one your application is running on) free to continue processing user input, while the other thread can process the data and return that processed data to the main thread when it is finished. Of course, computers can't actually do more than one thing at a time, but the magic of the operating system rapidly switching between one task and another means that you can simulate this. The mechanism for doing so involves threads.
The catch comes in the fact that the VB 6 environment does not have any type of support for creating multiple threads. You only get one thread, and that's the main thread that your application runs on. If you freeze execution of that one, even temporarily, your application freezes—as you've already found out.
However, if you're already writing a C++ DLL, there's no reason you can't create multiple threads in a VB 6 app. You just have to handle everything yourself as if you were using another lower-level language like C++. Run the C++ code on a background thread, and only return its results to the main thread when it is completely finished. In the mean time, your main thread is free.
This is still quite a bit of work, though, especially if you're inexperienced when it comes to Win32 programming and the issues surrounding multiple threads. It might be easier to find a different library that supports asynchronous function calls out-of-the-box. Antagony suggests using VB's AsyncRead method. That is probably a good option; as Karl Peterson says in the linked article, it keeps everything in pure VB 6 code, which can be a real time saver as well as a boon to future maintenance programmers. The only problem is that you'll still have to process the data somehow once you obtain it. And if that's slow, you're right back where you started from…
Check out this article, which demonstrates how to asynchronously transfer large files using a little-known method in user controls.

Low level keyboard Hook not at UI thread

I want to create a good library for keyboard hook. I use a method SetWindowsHookEx and I have noticed that method hookProc, which should be called at any system KeyDown event, is not executed if the main thread of my app is bussy. I think the hook shold be made so, that the other thread would be responsible for it. Is that possible? How can I do it?
Microsoft help page of LowLevelKeyboardProc mentions that
If the hook procedure times out, the system passes the message to the
next hook. However, on Windows 7 and later, the hook is silently
removed without being called. There is no way for the application to know whether the hook is removed.
I suspect this is what’s happening to you. Your HookProc function should be extremely fast: what mine does is just pushing the key event in a std::vector. The real code is executed in another thread.

Thread communication using SendMessage

my question is : how can I use SendMessage() to implement thread communication between two threads, one with a window (GUI) and the other with no window?
The problem is that SendMessage() needs a handle (HWND)?
Another detail about my project : Two threads, one running managed code (the one with the user interface), and the other running native code (the one without window)
Thank you very much!
I would suggest creating a hidden window. When using postthreadmessage, there is a chance that your message could get lost (ie: if a messagebox is running the message loop).
More info about that at:
http://blogs.msdn.com/oldnewthing/archive/2005/04/26/412116.aspx
Perhaps you should try to use PostMessage or PostThreadMessage
If the thread has no window, no message queue, and no message dispatcher, then it's going to be hard to a message to it. It is common for threads to create hidden windows just for communication purposes (take a look with Windows Spy and you'll see plenty of examples).
One alternative is to use shared memory and a synchronization primitive such an event or semaphore. Another alternative is to use pipes.
what #jdigital said. Note that if you create a hidden window, and your thread does not already implement a message loop (either in regular win32-speak, or one in the context of a COM STA -- and if you have no idea what I'm talking about then one probably does not exist in your thread), you'll also want to create a message loop as well. ATL makes it fairly easy with _AtlModule.RunMessageLoop(); Unfortunately this also means the thread in question is probably going to need to be event-driven while it is in the message loop. You can do tricky things like MsgWaitForMultipleObjects, but it gets hairy.
Here's an example of hidden windows if you're familiar with ATL/COM. I went through this pain a while back and thought there was a useful discussion on microsoft.public.vc.atl, but the best I can find now is this post. which goes into some detail about variants of message loops (what to do differently if you have keystroke accelerators or modeless windows, sounds like you don't in your application).

Resources