简体   繁体   English

wxWidgets GUI应用程序中的多线程?

[英]Multithreading in wxWidgets GUI apps?

I'm having problem (basically, I'm confused.) while trying to create a worker thread for my wxWidgets GUI application that WILL MODIFY one of the GUI property itself. 我在尝试为wxWidgets GUI应用程序创建一个工作线程时会遇到问题(基本上,我很困惑。),该工作线程将修改GUI属性本身之一。 (In this case, wxTextCtrl::AppendText). (在这种情况下,wxTextCtrl :: AppendText)。

So far, I have 2 source files and 2 header files for the wx program itself (excluding my own libs, MySQL lib, etc), say MainDlg.cpp which contains a derived class of wxFrame called 'MainDlg' and MainForm.cpp which contains a derived class of wxApp called 'MainForm'. 到目前为止,我有2个用于wx程序本身的源文件和2个头文件(不包括我自己的库,My​​SQL库等),例如MainDlg.cpp,其中包含名为“ MainDlg”的wxFrame派生类,而MainForm.cpp包含wxApp的派生类,称为“ MainForm”。

MainForm.cpp MainForm.cpp

#include "MainHeader.h" // contains multiple header files

IMPLEMENT_APP(MainForm)

bool MainForm::OnInit()
{
    MainDlg *Server = new MainDlg(wxT("App Server 1.0"), wxDEFAULT_FRAME_STYLE - wxRESIZE_BORDER - wxMAXIMIZE_BOX);
    Editor->Show();

    return true;
}

MainDlg.cpp: MainDlg.cpp:

#include "MainHeader.h"

BEGIN_EVENT_TABLE(MainDlg, wxFrame)
EVT_BUTTON(6, MainDlg::StartServer)
EVT_BUTTON(7, MainDlg::StopServer)
END_EVENT_TABLE()

CNETServerConnection *cnServCon;
std::string ServerIP, DBHost, DBUser, DBName, DBPass;
int UserCapacity, DBPort, ServerPort;
MYSQL *sqlhnd;

MainDlg::MainDlg(const wxString &title, long style) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(301, 230), style)
{
    cnServCon = new CNETServerConnection(100);
    this->InitializeComponent();
}

void MainDlg::InitializeComponent()
{
    this->SetTitle(wxT("App Server 1.0"));
    this->SetSize(396, 260);
    this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
    this->Centre();

    statBox = new wxTextCtrl(this, 4, wxT("Welcome to AppServer 1.0\n\n"), wxPoint(10, 10), wxSize(371, 141), wxTE_MULTILINE | wxTE_READONLY);

    //.................................
}

void MainDlg::StartServer(wxCommandEvent &event)
{
    this->startBtn->Enable(false);
    this->AppendStatus(wxT("\nLoading server configuration... "));

    //.................................

    this->AppendStatus(wxT("OK\n\nServer ready!\n\n"));

    // When the server is ready, I need to run a thread
    // that will update the statBox (through AppendStatus func or wxTextCtrl::AppendText directly)
    // regularly without interrupting the GUI itself.
    // Because the thread will contain a while-loop
    // to make the program keep receiving message from clients.

    this->startBtn->Hide();
    this->stopBtn->Show();
    this->cmdBtn->Enable();
    this->cmdBox->Enable();
}

void MainDlg::StopServer(wxCommandEvent &event)
{
    //...................................
}

void MainDlg::AppendStatus(const wxString &message)
{
    statBox->AppendText(message);
}

// Well, here is the function I'd like to run in a new thread
void MainDlg::ListenForMessages()
{
    int MsgSender = 0;
    while(1)
    {
        if(!cnServCon->GetNewMessage())
            continue;

        if(MsgSender = cnServCon->GetJoiningUser())
            this->AppendStatus(wxT("Someone connected to the server."));
    }
}

I also found an usage example of wxThread from Simple example of threading in C++ : 我还从C ++中的简单线程示例中找到了wxThread的用法示例:

class MessageThread : public wxThread
{
private:
    MessageThread(const MessageThread &copy);
public:
    MessageThread() : wxThread(wxTHREAD_JOINABLE)
    {
    }

    void *Entry(void)
    {
        // My works goes here
        return;
    }
};

wxThread *CreateThread()
{
        wxThread *_hThread = new MessageThread();

        _hThread->Create();
        _hThread->Run();

        return _hThread;
}

But I don't know how to associate it with my program and make it able to modify my GUI property (statBox). 但是我不知道如何将其与程序关联,并使其能够修改我的GUI属性(statBox)。

Any kind of help would be appreciated! 任何帮助将不胜感激! :) :)

Thanks. 谢谢。

The easiest is to create an event type id, and use a wxCommandEvent using the type id, set its string member ("evt.SetText"), and send the event to one of your windows (using AddPendingEvent ). 最简单的方法是创建一个事件类型id,并使用一个使用该类型id的wxCommandEvent ,设置其字符串成员(“ evt.SetText”),然后将该事件发送到您的一个窗口(使用AddPendingEvent )。 In the handler of that event, you can then call AppendText on your control using the text you sent ( evt.GetText ), because you are in the GUI thread by then. 然后,在该事件的处理程序中,您可以使用发送的文本( evt.GetText )在控件上调用AppendText ,因为此时您已处于GUI线程中。

// in header
DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1)

// in cpp file
DEFINE_EVENT_TYPE(wxEVT_MY_EVENT)

// the event macro used in the event table. id is the window id you set when creating 
// the `wxCommandEvent`. Either use -1 or the id of some control, for example. 
EVT_COMMAND(window-id, event-id, handler-function)

Here is an overview how it works: Custom Events . 以下是其工作原理的概述: 自定义事件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM