Threads in wxWidgets

I use wxWidgets and I call a function that takes a long time to continue. I would like to do this in the background.

How can i do this?

thanks for the help

+4
source share
4 answers

I have worked with threads in wxWidgets in almost all of the ways described below, and I can say that using custom events, while initially a bit more complicated, will save you some headache in the long run. (The wxMessageQueue class is pretty nice, but when I used it, I found that it was leaking, I did not check it in about a year.)

Basic example:

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

I feel this is a much more understandable and concise example than the one offered by the wiki. Obviously, I left the code regarding the actual launch of the application (the wx convention will do this MyApp.cpp) and any other non-thread related code.

+6
source

If you just need to work something in the background until it ends - fire and forget, if you like, something like this:

 // 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 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 
+2
source

A few tips for implementing the above:

  • Using MingW32 and Codeblocks, I had the following warning: EVENT redeclared without dllimport attribute: previous dllimport ignored . The bottom line is that if you do not need to export your events, use DEFINE_LOCAL_EVENT_TYPE and DECLARE_LOCAL_EVENT_TYPE (instead of DEFINE_EVENT_TYPE and DECLARE_EVENT_TYPE ).

  • If you want to pass objects through SetClientData() , make sure that you create data using the new operator in the removable stream. Then the calling application will have delete data after copying it.

For instance:

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

and in the calling application:

 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; } 
+2
source

If your program is simple and you do not want to interfere with threads, you can often call wxWindow :: Update () in its long function.

0
source

Source: https://habr.com/ru/post/1311551/


All Articles