Skip to content

Accessing the User Interface from a Thread

Perhaps you already knew, but with desktop apps it has always been considered bad form to directly access any part of your user interface from within a Thread. Alas, even though this was frowned upon, it generally worked in most of your desktop apps.

Starting with 2013r1, this no longer works with Xojo for Cocoa apps. If a Cocoa app tries to access the UI from a thread, a ThreadAccessingUIException is raised. But what exactly does “accessing the UI” mean? In the case of Cocoa, it means any access to a built-in property or method on any UI control or Window. You can access your own methods or properties added to control subclasses as long as they do not access the UI themselves.

Detecting Threaded UI Access

Running your project from Xojo is one way to detect if it is accessing the UI from a thread as the ThreadAccessingUIException will get raised and cause your app to terminate.

We also created a command-line tool that you can run on your existing Cocoa apps to help detect if they are using threads. The full details are covered in the Detecting UI Access from Threads blog post from last year.

Updating the UI

Of course, one of the main benefits of using a thread is to allow your UI to remain responsive while processing occurs, so you may need to update the UI with some indication of such progress.

Fortunately, there are other supported ways to accomplish this. Perhaps the most obvious is to use a Timer in conjunction with the thread. This technique is relatively straightforward. Instead of having the thread access the UI, you have a Timer on your Window that periodically gets progress information from the thread (perhaps from a property).

An example of this technique is included with the Xojo example projects: Desktop/Threading/Threaded UI Update.

ThreadingProjects.png

The example demonstrates how to update a ProgressBar using values from a thread.

Threaded UI Update Example.png

Also included with Xojo is an example of a Task class that can be used to do this as well. Task is a Thread subclass that has an UpdateUI event handler and method. In the Thread’s Run event handler, you call the UpdateUI method when you want to update any UI. Then in the UpdateUI event handler, you can have code that directly accesses the UI. Check out the example included with Xojo here: Desktop/Threading/Tasks. This example also demonstrates how to update a ProgressBar using values from a thread.

Both of these techniques demonstrate how you can modify your existing projects so that they work well with Cocoa. And even if your app does not need to run on Cocoa, you should still consider using these techniques. None of the major OS UI frameworks are thread-safe and although things mostly work on Windows, Linux and OS X Carbon, you could still run into unexplainable problems caused by directly accessing the UI from a thread.