Pooka SDK Developer Guide
UI Thread & Worker Thread

About UI Thread and Worker Thread

Regardless of the type of platform, every application is a process running on native operating system. A process can own one numbers of threads.

UI Thread

The UI thread, or "main thread", is the is the thread of execution for an application, which controls the lifecycle of the application, handle user input and performs rendering cycle, as well as executes scheduled tasks. In the figure shown at right-side, the UI thread is depicted by the yellow line with arrow indicates the control flow. UI thread is created by the operating system when the application (process) is launched, and is also terminated by operating system when the application (process) is terminated.

The Most Important Tasks Executed on UI Thread

Since the UI thread controls the application lifecycle, once UI thread reaches its end, the application terminates. Therefore in an GUI based application, an infinite main message loop (depicted by the green looping diagram block) is set up to loop infinitely to prevent application from terminating.

Where main message loop keeps UI thread and thus application alive, there are three major sequential tasks executed inside main message loop:

  • Handle user input: Pooling and queuing user input and dispatching event to the application to handle
  • Rendering cycle: Performing rendering cycle to refresh the application presentation or generating animation
  • Execute scheduled tasks: execute scheduled tasks on UI thread

Avoid Blocking UI Thread

Application code may run inside all these three stages. The most important rules of UI thread is that UI thread should never be block by a "lengthy: task. If the UI thread is locked for too long time, the application will appear to be irresponsible or freezing, which is considered a violation against all platform's application design guideline. Although the maximum tolerant UI blocking-time defined by each platforms varies, from less than 1 second to several seconds. This short irresponsible period may cause the application fail the platform certification. If any task can be foreseen a time-consuming task, the correct practice is put this task on a worker thread.

Worker Thread

In contrast with UI thread, any threads that are not UI thread are considered worker threads, or background threads. Worker threads are created by the application itself with the propose of completing certain job. This is where the worker threads get their name.

The purpose of creating a worker thread may be:

  • Allows a time-consuming task to run on a thread other than UI thread so that the UI thread will not be blocked
    Example of time-consuming task may be a huge amount of mathematic calculation, retrieving large amount of data from network, pooling data from hardware like sensor or GPS unit. All these kinds of tasks must be put on a worker thread.
  • Distribute the work load on multiple processor core, which can take advantage of the power of multi-core processor
    Most modern processors have 2, 4, 8 or even more cores nowadays and each core may be capable of running 2 threads at the same time. Multiple worker threads allow operating system distribute the computing workload across multiple cores for better application performance.

UI-Related Task Must be Executed on UI Thread

Any task that makes change in application content is considered a UI related task in Pooka SDK® application. Followings are some examples of UI related tasks:

  • Constructs a user interface for an online book store by interactive Sprites like buttons, check-box, list-box and etc.
  • Make UI element enabled or disabled according to the current state
  • Change UI element (Example: button, label) text
  • Add or remove items from a UI element (Example: items in a list-box, combo-box)
  • Remove a 2D Sprite in a 2D space shooting game, such as a alien UFO when it is destroyed, or a Spaceship's fire after it exploded.
  • Add a 2D Sprite in a 2D space shooting game, such as a new alien UFO come into the game scene.
  • Remove a 3D object in a 3D air combat game, such as armed chipper when it is shot down.
  • Add a 3D object in a 3D air combat game, such as a new flowing object carrying first-aid box come into the game scene.

Since UI-Related tasks modify the application content, they must be executed on UI thread to guarantee the consistency of the application content. Consider the an example of a UI related task, which deletes a button from application UI. If this task runs on a worker thread and at the moment it removes the button, the application's rendering cycle is just rendering the application content. As the result, this "removed" button might have been rendered on the display, or event worse, the rendering engine may crash because the class instance of that "removed" button has been destroyed.

There are two solutions to guarantee a UI related task is executed safely:

Solution 1 - Make the UI related tasks run on UI thread

Wrap the task by class Application::ScheduledTask and execute the task asynchronously by the function Application::postTask . The task will be executed at the next available safe moment inside the main message loop, which is running on the UI thread.
See class Application::ScheduledTask for more details.
Sample code:

class MyScheduledTask : public Application::Schedulable
{
public:
void run(Application::ScheduledTask * task)
{
... //The task code
}
void onStart(Application::ScheduledTask * task)
{
}
void onEnd(Application::ScheduledTask * task)
{
delete this; //Self destroy
}
};
// Note: ScheduledTask is always managed by Application class, so we should not delete it
Application::postTask(this, new MyScheduledTask(), L"CONTEXT_MY_SCHEDULE_TASK", NULL);

 Sample Project  Scheduled Task

Solution 2 - Let the UI related tasks run on worker thread but synchronized with UI thread

This solution lets the UI related tasks run on worker thread but synchronized with UI thread by wrapping the code by a pair of synchronization functions Application::syncUIThreadBegin() and Application::syncUIThreadEnd() . The task wrapped inside the synchronization functions is guaranteed to run only at the safe moment, which is the moment does not conflict with the UI thread activities, such as rendering the application UI.

Sample code:

void MyThread::run()
{
...
Application::syncUIThreadBegin(); //SYNC {
//UI related task, must be synchronized with UI thread
Sprite * sptProgressBar = this->_scene->getSprite(String(L"sptBar")+this->_no);
sptProgressBar->width = 0;
sptProgressBar->setText(L"0%");
((MainPage *)this->_scene->container)->onThreadTerminated(this->_no);
Application::syncUIThreadEnd(); //SYNC }
...
}

 Sample Project  Thread Synced with GUI