2010-06-01 21 views
4

我正在使用wxWidgets,并调用需要很长时间才能继续执行的功能。我想在后台执行此操作。wxWidgets中的线程

我该怎么做?

感谢您的帮助

+0

这可能有助于 http://docs.wxwidgets.org/trunk/classwx_thread_helper.html – Aif 2010-06-01 20:32:55

+0

这... http://wiki.wxwidgets.org/Inter-Thread_and_Inter-Process_communication – laher 2010-06-01 21:19:18

回答

2

如果你只需要有一些工作在后台,直到它完成 - 火,如果你会忘记,这样的事情:

// warning: off the top of my head ;-) 
class MyThread 
    : public wxThread 
{ 
public: 
    MyThread() : wxThread(wxTHREAD_DETACHED) 
    { 
    if(wxTHREAD_NO_ERROR == Create()) { 
     Run(); 
    } 
    } 
protected: 
    virtual ExitCode Entry() 
    { 
    // do something here that takes a long time 
    // it's a good idea to periodically check TestDestroy() 
    while(!TestDestroy() && MoreWorkToDo()) { 
     DoSaidWork(); 
    } 
    return static_cast<ExitCode>(NULL); 
    } 
}; 

MyThread* thd = new MyThread(); // auto runs & deletes itself when finished 
6

我使用过在wxWidgets中以几乎所有的方式描述here,我可以说使用自定义事件虽然最初有点复杂,但从长远来看可以节省一些头痛的问题。 (该wxMessageQueue类是相当不错的,但是当我使用它,我发现它泄漏;我没有在一年内检查它虽然。)

一个基本的例子:

MyFrm.cpp

#include "MyThread.h" 

BEGIN_EVENT_TABLE(MyFrm,wxFrame) 
    EVT_COMMAND(wxID_ANY, wxEVT_MYTHREAD, MyFrm::OnMyThread) 
END_EVENT_TABLE() 
void MyFrm::PerformCalculation(int someParameter){ 
    //create the thread 
    MyThread *thread = new Mythread(this, someParameter); 
    thread->Create(); 
    thread->Run(); 
    //Don't worry about deleting the thread, there are two types of wxThreads 
    //and this kind deletes itself when it's finished. 
} 
void MyFrm::OnMyThread(wxCommandEvent& event) 
{ 
    unsigned char* temp = (unsigned char*)event.GetClientData(); 
    //do something with temp, which holds unsigned char* data from the thread 
    //GetClientData() can return any kind of data you want, but you have to cast it. 
    delete[] temp; 
}  

MyThread.h

#ifndef MYTHREAD_H 
#define MYTHREAD_H 

#include <wx/thread.h> 
#include <wx/event.h> 

BEGIN_DECLARE_EVENT_TYPES() 
    DECLARE_EVENT_TYPE(wxEVT_MYTHREAD, -1) 
END_DECLARE_EVENT_TYPES() 

class MyThread : public wxThread 
{ 
    public: 
     MyThread(wxEvtHandler* pParent, int param); 
    private: 
     int m_param; 
     void* Entry(); 
    protected: 
     wxEvtHandler* m_pParent; 
}; 
#endif 

MyThread.cpp

#include "MyThread.h" 
DEFINE_EVENT_TYPE(wxEVT_MYTHREAD) 
MyThread::MyThread(wxEvtHandler* pParent, int param) : wxThread(wxTHREAD_DETACHED), m_pParent(pParent) 
{ 
    //pass parameters into the thread 
m_param = param; 
} 
void* MyThread::Entry() 
{ 
    wxCommandEvent evt(wxEVT_MYTHREAD, GetId()); 
    //can be used to set some identifier for the data 
    evt.SetInt(r); 
    //whatever data your thread calculated, to be returned to GUI 
    evt.SetClientData(data); 
    wxPostEvent(m_pParent, evt); 
    return 0; 
} 

我觉得这比维基提供的更清晰,简洁的例子。显然,我遗漏了有关实际启动应用程序的代码(wx约定会使MyApp.cpp)以及任何其他与线程无关的代码。

0

如果你的程序很简单,并且你不想乱搞线程,你可以考虑定期在你的long函数中调用wxWindow :: Update()

2

从实施上述的一些技巧:

  1. 使用MINGW32和代码块,我有以下warning: EVENT redeclared without dllimport attribute: previous dllimport ignored。如果您不需要导出活动,请使用DEFINE_LOCAL_EVENT_TYPEDECLARE_LOCAL_EVENT_TYPE(而不是DEFINE_EVENT_TYPEDECLARE_EVENT_TYPE)。

  2. 如果要通过SetClientData()传递对象,请确保在可拆卸线程中使用new运算符创建数据。一旦复制数据,调用应用程序将必须复制delete数据。

例如:

BEGIN_DECLARE_EVENT_TYPES() 
    DECLARE_LOCAL_EVENT_TYPE(wxEVT_CALC_THREAD, -1) 
END_DECLARE_EVENT_TYPES() 

void* MyThread::Entry() 
{ 
    wxCommandEvent evt(wxEVT_CALC_THREAD, GetId()); 
    // do some work 
    vector<map<int, int> > *vm = new vector<map<int, int> >(); 
    // perform operations with the object vm ... 
    evt.SetClientData((void*)vm); 
    wxPostEvent(m_pParent, evt); 
} 

,并在调用应用程序:

DEFINE_LOCAL_EVENT_TYPE(wxEVT_CALC_THREAD) 

// change this to your event table 
BEGIN_EVENT_TABLE(..., ...) 
    EVT_COMMAND(wxID_ANY, wxEVT_CALC_THREAD, ThreadDone) 
END_EVENT_TABLE() 

void ThreadDone(wxCommandEvent& event) 
{ 

    vector<map<int, int> > *temp = (vector<map<int, int> > *)event.GetClientData(); 
    // store the data in *temp 
    delete temp; 
}