Multi-threaded access of components in Delphi - multithreading

Can you suggest an approach when design-time components can be accessed both from general code (VCL or other) and from my own threads?
The problem is that when I have full control over my own threads I know exactly when I should access mutexes. In case of design-time elements I have no control at least of the code related to VCL.
One of the variants would be to wrap HandleMessage in a mutex access code. The idea behind this is that almost everything related to VCL comes from message processing code (the exception is direct SendMessage handling). But looking at the sources I see no "official" way to wrap message handling in any code fragment.

Don't even try to go there. Google for "global interpreter lock" (Python specific) to see what a bad idea such a bottleneck is.
If you need synchronized access to data, try to make the locked access as short as possible, and lock not any higher in the call chain than you absolutely must. If you have objects that are to be accessed from multiple threads, then synchronize inside their methods.

Related

Why is it wrong to access GUI elements from another thread? [duplicate]

This question already has answers here:
Why are most UI frameworks single threaded?
(6 answers)
Closed 7 years ago.
In every GUI library I've used (Swing, Android, Windows Forms, WPF) there's this golden rule saying that one cannot access or modify GUI elements from another thread (other than the GUI thread). I suppose this rule applies to any GUI library. Breaking this rule will most likely cause application to crash. However, I've been wondering recently, why is it so? I couldn't find any profound explanation. So what is the low-level explanation of this rule?
No piece of software is thread-safe unless it is explicitly designed and build to be so.
A GUI is a complex and stateful beast, making it thread-safe would be 'prohibitively expensive'.
There is a very simple reason for this. Usually UI functions are not thread-safe (as making them thread-safe would pessimize performance).
Of those you listed, some may be wrappers around existing mechanisms, so you have to answer the question indirectly via the underlying GUI framework. In case of multi-platform GUI frameworks like e.g. Qt, you will also have the lowest-common denominator that determines what is possible and what isn't.
Now, why is access to the GUI not thread-safe? In the cases where I'm most familiar with (win32 and X11), accesses are often performed indirectly by sending requests and sometimes waiting for the according answer. This usually works in an atomic way, even across process boundaries, so that is not directly cause of the problem. However, if you do so from multiple threads, the worst that can happen is that data is modified in an uncoordinated way. For example, if you read, modify and write the same widget from two threads, these operations might be interleaved, so that only one thread's modifications will actually be applied.
There are other reasons for not supporting cross-thread access:
In win32, the queue with the messages is thread-local, which means that only the thread that created a window will actually find and be able to handle messages for that window. I guess this a legacy from times where processes were single-threaded and the message queue was simply a global. Making it thread-local is the same approach as the one used for making errno thread-safe.
Another reason is that support objects are created inside a process that represent some GUI element. For example, the MFC (on top of win32) use a map from the OS' widget handle to a C++ object representing that object. That map is stored in thread-local storage (which follows the thread-local message queue) and the access to the C++ objects is not guarded by a mutex. Accessing these objects from different threads is bad, not because they represent GUI objects but because they are not synchronized, simple as that.
If you think about modifying the structure of a widget tree (like e.g. the DOM tree in a browser), you either have very detailed knowledge of what other parts of the application are doing or you need to lock access to the whole tree before every operation just to be safe. Needless to say, this effectively prevents any parallel operations, so you can also take the next step and require all operations to come from one thread and thus save the whole multithreading overhead.
That said, I believe that Qt and C# (and probably others) actually do support some cross-thread operations. They will work some (more or less obscure) magic that forwards the calls to the GUI thread and forwards the results back to the calling thread again. In other words, they try to make the necessary inter-thread communication more convenient for the programmer, while retaining the efficiency and simplicity of the single-threaded GUI. This is not restricted to GUI handling though but rather a general approach, only that it is especially important for the GUI.
As far as I know, that is simply not true: Every object in Java might be accesed concurrently, as far as thread-safe techniques are correctly applied. The fact is that Java Swing objects are mostly not prepared for multithreading, so you'll have to perform external synchronization.
There are several instances in which you need several threads to interoperate in a GUI: Games, visual effects, user events...
More information about the GUI and multithreading:
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

When do I need synchronize in TThread?

I know that you need synchronize (yourprocedure) to set e.g. a label's text.
But what about:
Reading a label's text.
Toggle/Set the label's enabled property.
Call other labels procedures/functions (e.g. onclick event).
Is there an easy rule to know/remember when I need to use synchronize?
PS.: Is synchronize similar to PostMessage/SendMessage?
Easy rule of thumb: ANY access to VCL UI components needs to be synchronized. That includes both reading and writing of UI control properties. Win32 UIs, most notably dialogs like MessageBox() and TaskDialog(), can be used directly in worker threads without synchronizing.
TThread.Synchronize() is similar to SendMessage() (in fact, it used to be implemented using SendMessage() internally in Delphi 5 and earlier). TThread.Queue() is similar to PostMessage().
Any time you access a VCL UI component, you need to implement some type of thread safety measure. This is also, typically, the case when you're accessing a variable or procedure that exists or will be accessed by another thread. However, you don't need to use the Synchronize method in all of these situations. There are other tools at your disposal, and Synchronize is not always your best solution.
Synchronize blocks both the main thread and the calling thread while it's performing the procedure that you pass to it, so overusing it can detract from the benefits of multi-threading. Synchronize is probably most commonly used for updating your UI, but if you find that you're having to use it really frequently, then it might not be a bad idea to check and see if you can restructure your code. I.E. do you really need to read labels from within your thread? Can you read the label before starting the thread and pass it into the thread's constructor? Can you handle any of these tasks in the thread's OnTerminate event handler?

Updating VCL from the same thread that created the UI. Why?

I know that I must call Synchronize to update the vcl from a thread that did not create the controls or send a message to the window.
I have often heard the word not thread safe but I can't find an actual explanation about what is happening.
I know the application might crash with an access violation, but again I don't know why?
Please shed a light on this topic.
One of the biggest causes of the thread-unsafety in the VCL UI controls is the TWinControl.Handle property getter. It is not just a simple read-only accessor of the control's HWND. It also creates the HWND if it does not exist yet. If a worker thread reads the Handle property when no HWND exists yet, it creates a new HWND within the worker thread context, which is bad because HWNDs are tied to the creating thread context, which would render the owning control pretty much inoperable at best since Windows messages for the control would not go through the main message loop anymore. But worse, if the main thread reads the same Handle property at the same time the worker thread does (for instance, if the main thread is dynamically recreating the Handle for any number of reasons), there is a race condition between which thread context creates the HWND that gets assigned as the new Handle, as well as a potential handle leak potential if both threads end up creating new HWNDs but only one can be kept and the other gets leaked.
Another offender to thread-unsafety is the VCL's MakeObjectInstance() function, which the VCL uses internally for assigning the TWinControl.WndProc() non-static class method as the message procedure of the TWinControl.Handle window, as well as assigning anyTWndMethod-typed object method as the message procedure of the HWND created by the AllocateHWnd() function (used by TTimer for example). MakeObjectInstance() does quite a bit of memory allocating/caching and twiddling of that memory content which are not protected from concurrent access by multiple threads.
If you can ensure a control's Handle is allocated ahead of time, and if you can ensure the main thread never recreates that Handle while the worker thread is running, then it is possible to safely send messages to that control from the worker thread without using Synchronize(). But it is not advisable, there are just too many factors that the worker thread would have to take into account. That is why it is best that all UI access be done in the main thread only. That is how the VCL UI system is meant to be used.
About GDI thread safety in Windows, see this reference article.
It clearly states that you can access safely handles from multiple threads, but that it should not be made at the same time. You need to protect access to GDI handles, e.g. using critical sections.
Remember that GDI handles, like most Windows handles, are pointers of internal structures mapped to an integer (NativeUInt under newer Windows, for 64 bit compatibility). Like always in multi-thread computing, accessing the same content concurrently can be source of problems, which are very difficult to identify and fix.
The UI part of the VCL itself was never meant to be thread-safe, from the beginning, since it was relying on the non-thread-safe Windows API. For instance, if you release a GDI object in a thread, which is still needed in another thread, you'll face potential GPF.
Embarcadero (at this time) could have made the VCL thread-safe, serializing all UI access via critical sections, but it may have added complexity, and decreased overall performance. Note that even Microsoft .Net platform (in both WinForms and WPF) also requires a dedicated thread for UI access, AFAIK.
So, to refresh UI from multiple threads, you have several patterns:
Use Synchronize calls from the thread;
Send a GDI custom message (see WM_USER) from the background threads to notify the UI thread that a refresh is needed;
Have a stateless approach: the UI will refresh its content from time to time, from the logic layer (using a timer or when you press some buttons which may change the data).
From my point of view, I prefer option 2 for most UIs, and an additional option 3 (which can be mixed with option 2) for remote client-server access. Therefore, you do not have to want from the server side to trigger some update event to the UI. In a HTTP/AJAX RESTful world, this does definitively make sense. Option 1 is somewhat slow, IMHO. In all cases, options 2 and 3 expect a clear n-Tier layered architecture, in which logic and UI are not mixed: but this is a good pattern to follow anyway, for any serious development.
Windows controls with handles are not thread-safe (i.e. they cannot be accessed safely by two different threads at the same time), and Delphi wraps the Windows controls to give you the VCL controls. Since the controls ARE accessed by the main GUI thread, you need to leave them alone if you are executing another thread.

Will this make the object thread-safe?

I have a native Visual C++ COM object and I need to make it completely thread-safe to be able to legally mark it as "free-threaded" in th system registry. Specifically I need to make sure that no more than one thread ever accesses any member variable of the object simultaneously.
The catch is I'm almost sure that no sane consumer of my COM object will ever try to simultaneously use the object from more than one thread. So I want the solution as simple as possible as long as it meets the requirement above.
Here's what I came up with. I add a mutex or critical section as a member variable of the object. Every COM-exposed method will acquire the mutex/section at the beginning and release before returning control.
I understand that this solution doesn't provide fine-grained access and this might slow execution down, but since I suppose simultaneous access will not really occur I don't care of this.
Will this solution suffice? Is there a simpler solution?
This solution should work, but I'd recommend mutexes over critical sections as they handle time-outs, which provide some level of fall back in case of deadlock. You also want to be very careful that a function locking a mutex does not call another function that has already locked the same mutex in the same thread. This shouldn't be a problem for your COM interface, so long as you don't add extra functionality on top of your mutex to the interface. You could hit issues if the COM includes call backs.
If you are certain that actual concurrent access is not going to happen in practice, then mutexing the entire execution is not an unreasonable approach.

Multiple UI threads on the same window

I don't want multiple windows, each with its own UI thread, nor events raised on a single UI thread, not background workers and notifications, none of that Invoke, BeginInvoke stuff either.
I'm interested in a platform that allows multiple threads to update the same window in a safe manner. Something like first thread creates three buttons, the second thread another five, and they both can access them,change their properties and delete them without any unwanted consequences.
I want safe multi-threaded access to the UI without Invoking, a platform where the UI objects can be accessed directly from any thread without raising errors like "The object can only be accessed from the thread that created it". To let me do the synchronizing if I have to, not prevent me from cross-tread accessing the UI in a direct manner.
I'm gonna get down voted but ... Go Go Gadget Soapbox.
Multi threaded GUI are not possible in the general case. It has been attempted time and time again and it never comes out well. It is not a coincidence that all of the major windowing frameworks follow the single threaded ui model. They weren't copying each other, it's just that the constraints of the problem lead them to the same answer. Many people smarter than you or i have tried to solve this.
It might be possible to implement a multi-thread ui for a particular project. I'm only saying that it can't be done in the general case. That means it's unlikely you'll find a framework to do what you want.
The gist of the problem is this. Envision the gui components as a chain (in reality it's more like a tree, but a chain is simple to describe). The button connects to the frame, connects to the box, connects to the window. There are two source of events for a gui the system/OS and the user. The system/OS event originate at the bottom of the chain (the windowing system), the user event originate at the top of the chain (the button). Both of these events must move through the gui chain. If two threads are pushing these events simultaneously they must be mutex protected. However, there is no known algorithm for concurrently traversing a double linked list in both directions. It is prone to dead lock. GUI experts tried and tried to figure out ways to get around the deadlocking problem, and eventually arrived at the solution we use today called Model/View/Controller, aka one thread runs the UI.
You could make a thread-safe Producer/Consumer queue of delegates.
Any thread that wants to update a UI component would create a delegate encapsulating the operations to be performed, and add it to the queue.
The UI thread (assuming all components were created on the same thread) would then periodically pull an item from the queue, and execute the delegate.
I don't believe a platform like that exists per se
There is nothing stopping you from saying taking .Net and creating all new controls which are thread safe and can work like that(or maybe just the subset of what you need) which shouldn't be an extremely large job(though definitely no small job) because you can just derive from the base controls and override any thread-unsafe methods or properties.
The real question though is why? It would definitely be slower because of all the locking. Say your in one thread that is doing something with the UI, well it has to lock the window it's working on else it could be changed without it knowing by the other thread. So with all the locking, you will spend most of your drawing time and such waiting on locks and (expensive) context switches from threads. You could maybe make it async, but that just doesn't seem safe(and probably isn't) because controls that you supposedly just created may or may not exist and would be about like
Panel p=new Panel();
Button b=new Button();
WaitForControlsCreated(); //waits until the current control queue is cleared
p.Controls.Add(b);
which is probably just as slow..
So the real question here is why? The only "good" way of doing it is just having an invoke abstracted away so that it appears you can add controls from a non-UI thread.
I think you are misunderstanding how threads really work and what it takes to actually make an object thread safe
Accept that any code updating the GUI has to be on the GUI thread.
Learn to use BeginInvoke().
On Windows, Window handles have thread affinity. This is a limitation of the Window manager. It's a bad idea to have multiple threads accessing the same window on Windows.
I'm surprised to see these answers.
Only the higher level language frameworks like C# have thread restrictions on GUI elements.
Windows, at the SDK layer, is 100% application controlled and there are no restrictions on threads except at insignificant nitty gritty level. For example if multiple threads want to write to a window, you need to lock on a mutex, get the device context, draw, then release the context, then unlock the mutex. Getting and releasing a device context for a moment of drawing needs to be on the same thread... but those are typically within 10 lines of code from each other.
There isn't even a dedicated thread that windows messages come down on, whatever thread calls "DispatchMessage()" is the thread the WINPROC will be called on.
Another minor thread restriction is that you can only "PeekMessage" or "GetMessage" a window that was created on the current thread. But really this is very minor, and how many message pumps do you need anyway.
Drawing is completely disconnected from threads in Windows, just mutex your DC's for drawing. You can draw anytime, from anywhere, not just on a WM_PAINT message.
BeOS / Haiku OS
Based on my guessing of your requirement, you want a single Windows Form and having ways to execute certain routines asynchronously (like multi-threading), yes?
Typically (for the case of .NET WinForms) Control.Invoke / Control.BeginInvoke is used to a certain effect what I think you want.
Here's an interesting article which might help: http://www.yoda.arachsys.com/csharp/threads/winforms.shtml

Resources