Переведите поток в отдельное состояние, вызвав pthread_detach()
в порожденном потоке, или при создании потока в основном потоке установите атрибуты pthread для этого потока в отдельное состояние. Теперь, когда поток отсоединен, вам не нужно вызывать pthread_join()
в основном потоке. Затем в самом порождаемом потоке перед выходом из потока поместите событие в очередь событий объекта WxWidgets, который породил поток, чтобы «объявить», что порожденный поток завершен. Наконец, добавьте обработчик для вашего события завершения потока в ваш объект WxWidget, чтобы обработать даже порожденный поток, помещенный в его очередь событий.
Например, вы можете создать событие, подобное THREAD_FINISHED_EVENT
, которое вы продвинете в поток событий в очередь событий объекта, который будет порождать потоки. Ваш код будет выглядеть следующим образом:
wxCommandEvent event(THREAD_FINISHED_EVENT, GetId());
//"this" points to the parent WxWidgets object spawning the threads
//and allows you to access the "this" pointer in the handler
event.SetEventObject(this);
//Send the event
this->AddPendingEvent(event);
Само событие будет обработано в главном потоке событий WxWidget, который устанавливает обработчик для события. Вам просто нужно предоставить обработчик для объекта WxWidget и определить само событие. Это можно сделать с помощью макроса DEFINE_EVENT_TYPE
, а затем добавить следующую строку в конструктор объекта WxWidget, который будет порождать сами потоки:
//myWxWidget::thread_handler is the handler for your thread ending events
Connect(widgetID, THREAD_FINISHED_EVENT, wxCommandEventHandler(myWxWidget::thread_handler))
Подводя итог, вот как выглядит некоторый теоретический объектный класс WxWidgets:
//myWindowThreadClass.hpp
#include <wx/wx.h>
#include <wx/event.h>
extern expdecl const wxEventType THREAD_FINISHED_EVENT;
class myWindowThreadClass: public wxWindow
{
public:
myWindowThreadClass(wxWindow* parent, int id);
//handler for the thread-ending event
void thread_handler(wxCommandEvent& event);
//pushes a thread event on the wxWidgets event-queue
//for myWindowThreadClass
void send_thread_event();
};
//myWindowThreadClass.cpp
#include <myWindowthreadClass.h>
#include <pthread.h>
const wxEventType THREAD_FINISHED_EVENT = wxNewEventType();
void* thread_func(void* data)
{
myWindowThreadClass* window_ptr = static_cast<myWindowThreadClass*>(data);
//detach thread
pthread_detatch(pthread_self());
//... rest of thread function
window_ptr->send_thread_event();
return (void*)0;
}
myWindowThreadClass::myWindowThreadClass(wxWindow* parent, int id):
wxWindow(parent, id)
{
//enable the event handler
Connect(id, THREAD_FINISHED_EVENT, wxCommandEventHandler(myWindowThreadClass::thread_handler));
//create your threads
pthread_t tid;
for (int i=0; i < NUM_THREADS; i++)
{
pthread_create(&tid, NULL, thread_func, this);
}
//...do anything else needed to initialize object
}
void myWindowThreadClass::thread_handler(wxCommandEvent& event)
{
//handle the event
}
void myWindowThreadClass::send_thread_event()
{
wxCommandEvent event(THREAD_FINISHED_EVENT, GetId());
event.SetEventObject(this);
//Send the event ... import to use this function, as it will cause
//the event to be processed in main-thread, not spawned child threads
this->AddPendingEvent(event);
}