October 19th Friday (十月 十九日 金曜日)

来源:互联网 发布:淘宝盗图怎么电话投诉 编辑:程序博客网 时间:2024/05/16 00:47
Types of wxThreads

  There are two types of threads in wxWidgets: detached and joinable, modeled after the the POSIX thread API.
This is different from the Win32 API where all threads are joinable.

  By default wxThreads in wxWidgets use the detached behavior. Detached threads delete themselves once they
have completed, either by themselves when they complete processing or through a call to wxThread::Delete, and
thus must be created on the heap (through the new operator, for example). Conversely, joinable threads do not
delete themselves when they are done processing and as such are safe to create on the stack. Joinable threads
also provide the ability for one to get value it returned from wxThread::Entry through wxThread::Wait.

  You shouldn't hurry to create all the threads joinable, however, because this has a disadvantage as well:
you must Wait() for a joinable thread or the system resources used by it will never be freed, and you also
must delete the corresponding wxThread object yourself if you did not create it on the stack. 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.


wxThread deletion

  Regardless of whether it has terminated or not, you should call wxThread::Wait on a joinable thread to
release its memory, as outlined in Types of wxThreads. If you created a joinable thread on the heap, remember
to delete it manually with the delete operator or similar means as only detached threads handle this type of
memory management.

  Since detached threads delete themselves when they are finished processing, you should take care when
calling a routine on one. If you are certain the thread is still running and would like to end it, you may
call wxThread::Delete to gracefully end it (which implies that the thread will be deleted after that call to
Delete()). It should be implied that you should never attempt to delete a detached thread with the delete
operator or similar means.

  As mentioned, wxThread::Wait or wxThread::Delete attempts to gracefully terminate a joinable and detached
thread, respectively. It does this by waiting until the thread in question calls wxThread::TestDestroy or
ends processing (returns from wxThread::Entry).

  Obviously, if the thread does call TestDestroy() and does not end the calling thread will come to halt.
This is why it is important to call TestDestroy() in the Entry() routine of your threads as often as possible.

  As a last resort you can end the thread immediately through wxThread::Kill. It is strongly recommended that
you do not do this, however, as it does not free the resources associated with the object (although the
wxThread object of detached threads will still be deleted) and could leave the C runtime library in an
undefined state.


wxWidgets calls in secondary threads

  All threads other then the "main application thread" (the one wxApp::OnInit or your main function runs in,
for example) are considered "secondary threads". These include all threads created by wxThread::Create or the
corresponding constructors.

  GUI calls, such as those to a wxWindow or wxBitmap are explicitly not safe at all in secondary threads and
could end your application prematurely. This is due to several reasons, including the underlying native API
and the fact that wxThread does not run a GUI event loop similar to other APIs as MFC.

  A workaround that works on some wxWidgets ports is calling wxMutexGUIEnter before any GUI calls and then
calling wxMutexGUILeave afterwords. However, the recommended way is to simply process the GUI calls in the
main thread through an event that is posted by either wxPostEvent or wxEvtHandler::AddPendingEvent. This does
not imply that calls to these classes are thread-safe, however, as most wxWidgets classes are not thread-safe, including wxString.


Don't poll a wxThread

  A common problem users experience with wxThread is that in their main thread they will check the thread
every now and then to see if it has ended through wxThread::IsRunning, only to find that their application
has run into problems because the thread is using the default behavior and has already deleted itself.
Naturally, they instead attempt to use joinable threads in place of the previous behavior.

  However, polling a wxThread for when it has ended is in general a bad idea - in fact calling a routine on
any running wxThread should be avoided if possible. Instead, find a way to notify yourself when the thread
has ended. Usually you only need to notify the main thread, in which case you can post an event to it via
wxPostEvent or wxEvtHandler::AddPendingEvent. In the case of secondary threads you can call a routine of another class when the thread is about to complete processing and/or set the value of a variable, possibly
using mutexes and/or other synchronization means if necessary.


wxMutex

  A mutex object is a synchronization object whose state is set to signaled when it is not owned by any
thread, and nonsignaled when it is owned. Its name comes from its usefulness in coordinating
mutually-exclusive access to a shared resource as only one thread at a time can own a mutex object.

  Mutexes may be recursive in the sense that a thread can lock a mutex which it had already locked before
(instead of dead locking the entire process in this situation by starting to wait on a mutex which will never
be released while the thread is waiting) but using them is not recommended and they are not recursive by
default. The reason for this is that recursive mutexes are not supported by all Unix flavours and, worse,
they cannot be used with wxCondition.

wxMutexLocker

  This is a small helper class to be used with wxMutex objects. A wxMutexLocker acquires a mutex lock in the
constructor and releases (or unlocks) the mutex in the destructor making it much more difficult to forget to
release a mutex (which, in general, will promptly lead to serious problems).


wxCriticalSection

A critical section object is used for exactly the same purpose as mutexes. The only difference is that under
Windows platform critical sections are only visible inside one process, while mutexes may be shared between
processes, so using critical sections is slightly more efficient. The terminology is also slightly different:
mutex may be locked (or acquired) and unlocked (or released) while critical section is entered and left by
the program.


wxCriticalSectionLocker

  This is a small helper class to be used with wxCriticalSection objects. A wxCriticalSectionLocker enters
the critical section in the constructor and leaves it in the destructor making it much more difficult to
forget to leave a critical section (which, in general, will lead to serious and difficult to debug problems).


wxCondition

  wxCondition variables correspond to pthread conditions or to Win32 event objects. They may be used in a
multithreaded application to wait until the given condition becomes true which happens when the condition
becomes signaled.

  For example, if a worker thread is doing some long task and another thread has to wait until it is
finished, the latter thread will wait on the condition object and the worker thread will signal it on exit
(this example is not perfect because in this particular case it would be much better to just Wait() for the
worker thread, but if there are several worker threads it already makes much more sense).

  Note that a call to Signal() may happen before the other thread calls Wait() and, just as with the pthread
conditions, the signal is then lost and so if you want to be sure that you don't miss it you must keep the
mutex associated with the condition initially locked and lock it again before calling Signal(). Of course,
this means that this call is going to block until Wait() is called by another thread.


wxSemaphore

  wxSemaphore is a counter limiting the number of threads concurrently accessing a shared resource. This
counter is always between 0 and the maximum value specified during the semaphore creation. When the counter
is strictly greater than 0, a call to Wait returns immediately and decrements the counter. As soon as it
reaches 0, any subsequent calls to Wait block and only return when the semaphore counter becomes strictly
positive again as the result of calling Post which increments the counter. 
原创粉丝点击