Wxwidgets 回调

发布于 2024-12-09 04:59:49 字数 309 浏览 0 评论 0原文

我想向线程函数添加回调函数而不冻结主应用程序。

例如:当我单击按钮时,它会启动一个线程函数。我想在工作完成时通知用户。

谢谢

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

pthread_join 在等待线程完成时阻止主应用程序。那我该怎么办呢。非常感谢

i would like to add a callback function to a threaded function without freezing the main application.

Ex: when I click on a button, it start a threaded function. I wanna inform the user when the work is finish.

Thx

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

The pthread_join block the main application when waiting for the thread to finish. So how would I do it. Thx a lot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

牵你的手,一向走下去 2024-12-16 04:59:49

通过在生成的线程中调用 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);
}

Make the thread in a detached state by calling pthread_detach() in the spawned thread, or when creating the thread in the main thread, set the pthread attributes for that thread to a detached state. Now that the thread is detached, you won't need to call pthread_join() in the main thread. Next, in the spawned thread itself, before exiting the thread, push an event onto event queue of the WxWidgets object that spawned the thread in order to "announce" that the spawned thread has completed. Finally, add an event handler for your thread-finishing event to your WxWidget object to handle the even the spawned thread will place on it's event queue.

For instance, you could create an event like THREAD_FINISHED_EVENT that you thread will push onto the event-queue of the object that will spawn the threads. You code would look like the following:

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);

The event itself will be processed in the main event thread of the WxWidget that installs the handler for the event. You'll just need to provide a handler for the WxWidget object, and define the event itself. This can be done using the macro DEFINE_EVENT_TYPE, and then adding the following line to the constructor of the WxWidget object that will be spawning the threads themselves:

//myWxWidget::thread_handler is the handler for your thread ending events
Connect(widgetID, THREAD_FINISHED_EVENT, wxCommandEventHandler(myWxWidget::thread_handler))

Summing this all up, here's what some theoretical WxWidgets object class would look like:

//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);
}
一影成城 2024-12-16 04:59:49

设置一个变量,例如。 xxx_is_done,在启动线程之前设置为false。当线程完成时,它所做的最后一件事是将 xxx_is_done 设置为 true。然后只需检查主事件循环中的变量,并在变量为 true 时在线程上调用 pthread_join ,并将变量设置回 false 这样就不会调用 < code>pthread_join 再次在线程上。

Set a variable, eg. xxx_is_done, to false before starting the thread. And when the thread is done, the last thing it does is set xxx_is_done to true. Then just check the variable in the main event loop and call pthread_join on the thread when the variable is true and also set the variable back to false so you don't call pthread_join on the thread again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文