Wxwidgets обратный вызов - PullRequest
       6

Wxwidgets обратный вызов

4 голосов
/ 10 октября 2011

Я хотел бы добавить функцию обратного вызова в многопоточную функцию, не останавливая основное приложение.

Пример: когда я нажимаю на кнопку, она запускает многопоточную функцию.Я хочу сообщить пользователю, когда работа закончится.

Thx

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

pthread_join блокирует основное приложение, ожидая завершения потока.Так как бы я это сделал.Огромное спасибо

Ответы [ 2 ]

4 голосов
/ 10 октября 2011

Переведите поток в отдельное состояние, вызвав 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);
}
1 голос
/ 10 октября 2011

Установить переменную, например. xxx_is_done, до false до начала потока. И когда поток завершен, последняя вещь, которую он делает, устанавливается xxx_is_done в true. Затем просто проверьте переменную в главном цикле событий и вызовите pthread_join в потоке, когда переменная равна true, а также установите переменную обратно в false, чтобы вы больше не вызывали pthread_join в потоке.

...