Using wxThread
If you want to implement functionality using threads, you write a class that derives from wxThread and implements at least the virtual EnTRy method, which is where the work of the thread takes place. Let's say you wanted to use a separate thread to count the number of colors in an image. Here's the declaration of the thread class:
The Entry function does the calculation and returns an exit code that will be returned by Wait (for joinable threads only). Here's the implementation for EnTRy:
class MyThread : public wxThread
{
public:
MyThread(wxImage* image, int* count):
m_image(image), m_count(count) {}
virtual void *Entry();
private:
wxImage* m_image;
int* m_count;
};
// An identifier to notify the application when the
// work is done
#define ID_COUNTED_COLORS 100
For simplicity, we're using an existing event class to send a notification to the application when the color count is done.
void *MyThread::Entry()
{
(* m_count) = m_image->CountColours();
// Use an existing event to notify the application
// when the count is done
wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,
ID_COUNTED_COLORS);
wxGetApp().AddPendingEvent(event);
return NULL;
}
Creation
Threads are created in two steps. First the object is instantiated, and then the Create method is called:
There are two different types of threads: the ones that you start and then forget about and the ones from which you are awaiting a result. The former are called detached threads, and the latter are joinable threads. Thread type is indicated by passing wxTHREAD_DETACHED (the default) or wxThrEAD_JOINABLE to the constructor of a wxTHRead. The result of a joinable thread is returned by the Wait function. You cannot wait for a detached thread.You shouldn't necessarily create all threads as joinable, however, because joinable threads have a disadvantage; you must wait for the thread using wxThread::Wait or else the system resources that it uses will never be freed, and you must delete the corresponding wxTHRead object yourself (once used, it cannot be reused). In contrast, detached threads are of the "fire-and-forget" kind. You only have to start a detached thread, and it will terminate and destroy itself.This means, of course, that all detached threads must be created on the heap because the thread will call delete this upon termination. Joinable threads may be created on the stack, although usually they will be created on the heap as well. Don't create global thread objects because they allocate memory in their constructor, which will cause problems for the memory checking system.
MyThread *thread = new MyThread();
if ( thread->Create() != wxTHREAD_NO_ERROR )
{
wxLogError(wxT("Can't create thread!"));
}
Specifying Stack Size
You can indicate the desired stack size for the thread as a parameter for Create. Passing zero tells wxWidgets to use the platform default.
Specifying Priority
Some operating systems let the application supply a hint about how much execution time a thread needs. Call wxThread::SetPriority with a number between 0 and 100, where 0 is the minimum and 100 is the maximum. The symbols WXThrEAD_MIN_PRIORITY, wxThrEAD_DEFAULT_PRIORITY, and wxThrEAD_MAX_ PRIORITY are predefined, with values 0, 50, and 100, respectively. You should call SetPriority after calling Create but before calling Run.
Starting the Thread
After calling Create, the thread is not yet running. You need to call wxThread:: Run to start the thread, and wxWidgets will call the thread's Entry function.
How to Pause a Thread or Wait for an External Condition
If a thread needs to wait for something to happen, you should avoid both polling and idling in a loop that keeps the processor busy doing nothing ("busy waiting").Synchronization Objects").
Termination
As we have mentioned, detached threads are automatically destroyed after completion. For a joinable thread, you can simply call wxTHRead::Wait immediately, or in a GUI application, you can poll wxThread::IsAlive from an idle handler in the main thread and only call Wait if IsAlive returns false. Calling Wait permits thread resources to be freed. Of course, a neater alternative is to simply use a detached thread and post an event when it's done.You can use wxTHRead::Delete to request that a thread be deleted. For this to work, the thread must periodically call TestDestroy.