I've recently come across the Worker & WorkerDomain classes available to AS3, however there doesn't seem any mention of how each thread interacts with whats being rendered on screen.
Is there a way to render to the screen on one thread, then after an
event switch rendering to the other thread?
My initial assumption is threads apart from the "Primordial" thread should only be used for background processing, but I'm hoping that may not be the case.
Related
I'm working on a simulation model that iterates over time steps. At times when the model results start to go South, I want to be able to click on a button to halt the iteration. However, if my testing is correct, when the iteration is running in the UI thread, the Button.Click event is not actuated because the thread is busy iterating. Is that correct? Is there a way to interrupt the UI thread with a button click when the thread is really busy?
One way to handle this problem is to create a Task using the Task Parallel Library to do the computationally-heavy iterations. I'm starting to work on this approach in case there is no way to interrupt the UI thread but I thought I'd check here to make sure I'm not missing a simpler approach.
The problem with your idea to interrupt your calculations on the UI thread is that it requires the cooperation of the UI thread, which is already slammed doing your calculating. For the UI thread to be able to process your button click the calculating needs to stop so the thread can go back to processing UI events. That means saving your progress so you can pick up where you left off later.
This kind of pausing and resuming seems likely to be more trouble than spinning the computation off into its own thread, it is not totally undo-able (the Netscape browser that JWZ developed worked like this, in a single thread), but the reason the multithreaded approach is encouraged is because it's the way that requires the least work, and keeps your calculation code the most focused on the domain and the least chopped up.
If you put the computation in its own thread then the UI thread will be responsive, the OS will make sure both threads get to run. You can make the calculation check for interruption periodically, you can have a progress bar with a cancel button, and you won't have to worry about stopping work to process UI events.
I'm assuming a UI where you have a single event dispatch thread that is responsible for handling UI events. This is how Swing works in Java and it's a popular choice for lots of GUI toolkits because multithreaded solutions are susceptible to deadlocks (events coming from the user will acquire locks in a different order than events coming from the back end). You can specify tags for language and platform to get more relevant answers.
The SDL documentation for threading states:
NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one.
The glfw documentation for glfwCreateWindow states:
Thread safety: This function must only be called from the main thread.
I have read about issues regarding the glut library from people who have tried to run the windowing functions on a second thread.
I could go on with these examples, but I think you get the point I'm trying to make. A lot of cross-platform libraries don't allow you to create a window on a background thread.
Now, two of the libraries I mentioned are designed with OpenGL in mind, and I get that OpenGL is not designed for multithreading and you shouldn't do rendering on multiple threads. That's fine. The thing that I don't understand is why the rendering thread (the single thread that does all the rendering) has to be the main one of the application.
As far as I know, neither Windows nor Linux nor MacOS impose any restrictions on which threads can create windows. I do know that windows have affinity to the thread that creates them (only that thread can receive input for them, etc.); but still that thread does not need to be the main one.
So, I have three questions:
Why do these libraries impose such restrictions? Is it because there is some obscure operating system that mandates that all windows be created on the main thread, and so all operating systems have to pay the price? (Or did I get it wrong?)
Why do we have this imposition that you should not do UI on a background thread? What do threads have to do with windowing, anyways? Is it not a bad abstraction to tie your logic to a specific thread?
If this is what we have and can't get rid of it, how do I overcome this limitation? Do I make a ThreadManager class and yield the main thread to it so it can schedule what needs to be done in the main thread and what can be done in a background thread?
It would be amazing if someone could shed some light on this topic. All the advice I see thrown around is to just do input and UI both on the main thread. But that's just an arbitrary restriction if there isn't a technical reason why it isn't possible to do otherwise.
PS: Please note that I am looking for a cross platform solution. If it can't be found, I'll stick to doing UI on the main thread.
While I'm not quite up to date on the latest releases of MacOS/iOS, as of 2020 Apple UIKit and AppKit were not thread safe. Only one thread can safely change UI objects, and unless you go to a lot of trouble that's going to be the main thread. Even if you do go to all the trouble of closing the window manager connection etc etc you're still going to end up with one thread only doing UI. So the limitation still applies on at least one major system.
While it's possibly unsafe to directly modify the contents of a window from any other thread, you can do software rendering to an offscreen bitmap image from any thread you like, taking as long as you like. Then hand the finished image over to the main thread for rendering. (The possibly is why cross platform toolkits disallow/tell you not to. Sometimes it might work, but you can't say why, or even that it will keep working.)
With Vulkan and DirectX 12 (and I think but am not sure Metal) you can render from multiple threads. Woohoo! Of course now you have to figure out how to do all the coordination and locking and cross-synching without making the whole thing slower than single threaded, but at least you have the option to try.
Adding to the excellent answer by Matt, with Qt programs you can use invokeMethod and postEvent to have background threads update the UI safely.
It's highly unlikely that any of these frameworks actually care about which thread is the 'main thread', i.e., the one that called the entry point to your code. The real restriction is that you have to do all your UI work on the thread that initialized the framework, i.e., the one that called SDL_Init in your case. You will usually do this in your main thread. Why not?
Multithreaded code is difficult to write and difficult to understand, and in UI work, introducing multithreading makes it difficult to reason about when things happen. A UI is a very stateful thing, and when you're writing UI code, you usually need to have a very good idea about what has happened already and what will happen next -- those things are often undefined when multithreading is involved. Also, users are slow, so multithreading the UI is not really necessary for performance in normal cases. Because of all this, making a UI framework thread-safe isn't usually considered beneficial. (multithreading compute-intensive parts of your rendering pipeline is a different thing)
Single-threaded UI frameworks have a dispatcher of some sort that you can use to enqueue activities that should happen on the main thread when it next has time. In SDL, you use SDL_PushEvent for this. You can call that from any thread.
Listed below are some API issues I expect to encounter when adding a render thread to code so that all graphics API calls that used to all occur on the main thread now occur on a dedicated background thread.
For Direct3D and OpenGL on Win32, are there additional issues that are involved that I'm not aware of, or has my list covered it?
List of expected issues:
D3D9: http://msdn.microsoft.com/en-us/library/windows/desktop/bb147224%28v=vs.85%29.aspx . This basically means allowance has to be made for particular special operations to occur on the main thread with D3D9.
D3D10+: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417025.aspx#Multithreading_and_DXGI . This basically means that the main thread (with the message pump) shouldn't block waiting on the render thread (specifically, for the render thread to make DXGI calls).
OpenGL: no issues so long as the context is only active on the render thread, but as above some care during mode changes, etc.
Note: assume my application has been careful to store and isolate all of the data the render thread will require to complete its processing, such as input buffer data, etc. I am asking specifically about window system and API-level issues and any gotchas.
My Windows application has a tabbed interface. Every tab will render some UI stuff. As everyone knows, if I do a very time consuming for-loop in the main thread without let other to process any Windows messages, the application will be frozen. During the frozen period, I cannot switch tabs.
I was inspired by the multiple process architecture of Google Chrome. I try to use SetParent to embed a process into another process. To be more specific: Process A is the master. It can create unlimited worker processes. Every worker process has its own message loop. If process B is frozen, process A and any other worker processes should not be frozen.
Actually I am wrong: If I click a button worker process B to do a lot of UI stuff in main thread without a break, not only the UI of process B but also the UI of process A will be blocked, until my test code ends.
Can somebody share some lights to me?
What you are attempting to do is, er, tricky to get right. I suggest that you start by reading Raymond Chen's article: Is it legal to call have a cross-process parent/child or owner/owned window relationship
Creating a cross-thread parent/child or owner/owned window relationship implicitly attaches the input queues of the threads which those windows belong to, and this attachment is transitive: If one of those queues is attached to a third queue, then all three queues are attached to each other. More generally, queues of all windows related by a chain of parent/child or owner/owned or shared-thread relationships are attached to each other.
This is exactly the scenario that you describe. And the fusing of all the message queues is to be expected. The fact that you have multiple processes doesn't change the fact that you must not block UI threads.
So I think that your program design is flawed. You are adding an epic amount of complexity, with no reward. The benefits of a multi-process architecture are security and isolation. You don't change anything with regards to blocking UI threads. The only way to solve your problem is to put the long running task on a non-UI thread. My strong advice is to return to a single process design.
I am trying to come up with a synchronization model for the following scenario:
I have a GUI thread that is responsible for CPU intensive animation + blocking I/O. The GUI thread retrieves images from the network (puts them in a shared buffer) , these images are processed (CPU intensive operation..done by a worker thread) and then these images are animated ( again CPU intensive..done by the GUI thread).
The processing of images is done by a worker thread..it retrieves images from the shared buffer processes them and puts them in an output buffer.
There is only once CPU and the GUI thread should not get scheduled out while it is animating the images (the animation has to be really smooth). This means that the work thread should get the CPU only when the GUI thread is waiting for I/O operation to complete.
How do i go about achieving this? This looks like a classic producer consumer problem...but i am not quite sure how i can guarantee that the animation will be as smooth as possible ( i am open to using more threads).
I would like to use QThreads (Qt framework) for platform independence but i can consider pthreads for more control ( as currently we are only aiming for linux).
Any ideas?
EDIT:
i guess the problems boils down to one thing..how do i ensure that the animation thread is not interrupted while it is animating the images ( the animation runs when the user goes from one page to the other..all the images in the new page are animated before shown in their proper place..this is a small operation but it must be really smooth).The worker thread can only run when the animation is over..
Just thinking out loud here, but it sounds like you have two compute-intensive tasks, animation and processing, and you want animation to always have priority over processing. If that is correct then maybe instead of having these tasks in separate threads you could have a single thread that handles both animation and processing.
For instance, the thread could have two task-queues, one for animation jobs and one for processing jobs, and it only starts a job from the processing queue when the animation queue is empty. But, this will only work well if each individual processing job is relatively small and/or interruptible at arbitrary positions (otherwise animation jobs will get delayed, which is not what you want).
The first big question is: Do I really need threads? Qt 's event system and network objects make it easy to not having the technical burden of threads and all the snags that comes with it.
Have a look at alternative ways to address issues here and here. These techniques great if you are sticking to pure Qt code and do not depend on a 3rd party library. If you must use a 3rd party lib that does blocking calls then sure, you can use threads.
Here is an example of a consumer producer.
Also have a look at Advanced Qt Programming: Creating Great Software with C++ and Qt 4
My advice is to start without threads and see how it fares. You can always refactor to threads after. So, best is to design your objects/architecture without too much coupling.
If you want you can post some code to give more context.