2011-10-10 35 views
4

我想在不凍結主應用程序的情況下爲線程函數添加回調函數。例如:當我點擊一個按鈕時,它啓動一個線程函數。工作完成後,我想告知用戶。Wxwidgets回調

THX

cs functions; 
    pthread_t thread; 
    pthread_create(&thread, NULL, maFonction, (void*)&functions); 
    //pthread_join(thread, NULL); 

的在pthread_join塊等待時的線程完成主應用程序。那麼我該怎麼做。 Thx很多

回答

4

在衍生的線程中調用pthread_detach(),或在主線程創建線程時進行的分離狀態的線程,設置該線程分離狀態的並行線程屬性。現在線程已分離,您不需要在主線程中調用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); 
} 
+0

比我的答案好多了!我有點太累了,不能直想......:/ –

+0

Thx很多,我會試試這個 – Naster

1

設置一個變量,例如。 xxx_is_done,至false開始線程之前。當線程完成時,它所做的最後一件事是將xxx_is_done設置爲true。然後只需在主事件循環中檢查變量,並在變量爲true時在線程上調用pthread_join,並將變量重新設置爲false,這樣您就不會再次在線程上調用pthread_join