темы в wxWidgets - PullRequest
       16

темы в wxWidgets

5 голосов
/ 02 июня 2010

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

Как я могу это сделать?

Спасибо за помощь

Ответы [ 4 ]

7 голосов
/ 19 июля 2010

Я работал с потоками в wxWidgets практически всеми способами, описанными здесь , и я могу сказать, что использование пользовательских событий, хотя поначалу немного сложнее, избавляет вас от головной боли в долгосрочной перспективе. запустить. (Класс 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) и любой другой не связанный с потоками код.

2 голосов
/ 05 сентября 2015

Несколько советов по реализации вышеперечисленного:

  1. Используя MingW32 и кодовые блоки, у меня было следующее warning: EVENT redeclared without dllimport attribute: previous dllimport ignored. Суть в том, что если вам не нужно экспортировать события, используйте DEFINE_LOCAL_EVENT_TYPE и DECLARE_LOCAL_EVENT_TYPE (вместо DEFINE_EVENT_TYPE и DECLARE_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;
}
2 голосов
/ 16 июля 2010

Если вам просто нужно, чтобы что-то работало в фоновом режиме, пока оно не закончилось - выстрелите и забудьте, если хотите, что-то вроде этого:

// 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
0 голосов
/ 22 сентября 2010

Если ваша программа проста и вы не хотите возиться с потоками, вы можете периодически вызывать wxWindow :: Update () в вашей длинной функции.

...