wxWidgets多线程及事件传递

前言

​ 最近忙着写项目,wxWidgets计划还有wxWidgets日志系统的拦截重定向,剩下一些比较杂的知识点,想到哪写到哪。比如进程间通信、调用外部程序后结束本程序(用于升级程序)、集成带窗口的ActiveX、创建单进程程序等,这些文档上基本都有。下面开始多线程的应用。

代码示例

​ 废话不多说,此示例演示,子线程进程业务处理完之后通知主线程,等待主线程执行完,子线程接着处理业务的过程。

​ 主要内容在主窗口文件和线程文件里面

​ 主窗口头文件:

/***************************************************************
 * Name:      blog_WidgetsMain.h
 * Purpose:   Defines Application Frame
 * Author:     ()
 * Created:   2021-02-23
 * Copyright:  ()
 * License:
 **************************************************************/

#ifndef BLOG_WIDGETSMAIN_H
#define BLOG_WIDGETSMAIN_H

#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

#include "blog_WidgetsApp.h"
enum SIGN_NUM{
    SIGN_1 = 8000,
    BTN1,
    BTN2
};

class blog_WidgetsFrame: public wxFrame
{
    public:
        blog_WidgetsFrame(){}
        blog_WidgetsFrame(wxFrame *frame, const wxString& title);
        ~blog_WidgetsFrame();
    public:
        wxMutex* mutex;//互斥量
        wxCondition* condition;//条件变量
        wxString speak;//主线程要说的话
    protected:
        //接收子线程发送的信号
        void OnThreadEvent(wxThreadEvent& event);
        //按钮1的事件,创建子线程,并启动
        void OnBtnStartEvent(wxCommandEvent& event);
        //按钮2的事件,通知子线程继续
        void OnBtnChildrenEvent(wxCommandEvent& event);
        //唤醒子线程
        void SendSign();
    private:
        //将类加入到RTTI中,供类型转换使用,可以使用wxDynamicCast进行转换
        DECLARE_DYNAMIC_CLASS(blog_WidgetsFrame);
        //定义事件表
        DECLARE_EVENT_TABLE()

};


#endif // BLOG_WIDGETSMAIN_H

​ 主窗口实现文件:

/***************************************************************
 * Name:      blog_WidgetsMain.cpp
 * Purpose:   Code for Application Frame
 * Author:     ()
 * Created:   2021-02-23
 * Copyright:  ()
 * License:
 **************************************************************/


#include "blog_WidgetsMain.h"
#include "ChildrenThread.h"


IMPLEMENT_DYNAMIC_CLASS(blog_WidgetsFrame,wxFrame)
BEGIN_EVENT_TABLE(blog_WidgetsFrame, wxFrame)
//绑定子线程发出的信号函数
    EVT_THREAD(SIGN_1,blog_WidgetsFrame::OnThreadEvent)
    //绑定接收button的信号函数,这里因为wxCommandEvent是事件可以传播的,主窗口也能接收到button的信号
    EVT_BUTTON(BTN1,blog_WidgetsFrame::OnBtnStartEvent)
    EVT_BUTTON(BTN2,blog_WidgetsFrame::OnBtnChildrenEvent)
END_EVENT_TABLE()

blog_WidgetsFrame::blog_WidgetsFrame(wxFrame *frame, const wxString& title)
    : wxFrame(frame, -1, title)
{
    mutex = new wxMutex();
    condition = new wxCondition(*mutex);

    //增加一个按钮,点击按钮后通知子线程接着执行
    wxButton* button1 = new wxButton(this,BTN1,wxT("开始"));
    wxButton* button2 = new wxButton(this,BTN2,wxT("通知子线程"));
    //添加到布局里面
    wxBoxSizer* box = new wxBoxSizer(wxVERTICAL);
    box->Add(button1,1,wxALL,0);
    box->Add(button2,1,wxALL,0);
    this->SetSizer(box);
}


blog_WidgetsFrame::~blog_WidgetsFrame()
{
    if(condition)
	{
		delete condition;
		condition = NULL;
	}
	if(mutex)
	{
		delete mutex;
		mutex = NULL;
	}
}
void blog_WidgetsFrame::OnThreadEvent(wxThreadEvent& event)
{
    wxString text = event.GetString();
    wxMessageBox(text,wxT("子线程"));
}

 void blog_WidgetsFrame::OnBtnStartEvent(wxCommandEvent& event)
 {
    //建立子线程
	ChildrenThread* childrenThread = new ChildrenThread(this);
	//运行子线程,分离线程无需手动销毁
	if(childrenThread != NULL)
	{
		if(childrenThread->Create()== wxTHREAD_NO_ERROR)
		{
            childrenThread->Run();
		}
	}
 }
void blog_WidgetsFrame::OnBtnChildrenEvent(wxCommandEvent& event)
{
    SendSign();
}



void blog_WidgetsFrame::SendSign()
{
    wxMutexLocker lock(*mutex);
	condition->Signal();
}

子线程头文件:

#ifndef CHILDRENTHREAD_H
#define CHILDRENTHREAD_H

#include <wx/wx.h>
#include "../blog_WidgetsMain.h"
class ChildrenThread: public wxThread
{
    public:
        ChildrenThread(wxFrame* frame);
        virtual ~ChildrenThread();
		virtual void* Entry();
		void threadWait(wxThreadEvent& event);
    protected:

    private:
        wxFrame* m_frame;
};

#endif // CHILDRENTHREAD_H

子线程实现文件:

#include "ChildrenThread.h"

ChildrenThread::ChildrenThread(wxFrame* frame):wxThread(wxTHREAD_DETACHED)//分离线程
{
    m_frame = frame;
}
ChildrenThread::~ChildrenThread()
{

}
void* ChildrenThread::Entry()
{
    blog_WidgetsFrame* frame = wxDynamicCast(m_frame,blog_WidgetsFrame);
    if(frame)
    {
        //获取锁
        frame->mutex->Lock();
        wxThreadEvent evt1(wxEVT_COMMAND_THREAD,SIGN_1);
        evt1.SetString(wxT("子线程第一次执行的结果通知"));
        //发送信号,并等待主线程通知
        threadWait(evt1);

        wxThreadEvent evt2(wxEVT_COMMAND_THREAD,SIGN_1);
        evt2.SetString(wxT("子线程第二次执行的结果通知"));
        //直接发送信号,不在等待主线程
        frame->GetEventHandler()->QueueEvent(evt2.Clone());

        //最后记着释放锁
        frame->mutex->Unlock();
    }
    return NULL;
}
void ChildrenThread::threadWait(wxThreadEvent& event)
{
    blog_WidgetsFrame* frame = wxDynamicCast(m_frame,blog_WidgetsFrame);
    frame->GetEventHandler()->QueueEvent(event.Clone());
    frame->condition->Wait();

}

调用文件就不贴出来了,简单的父子线程协同工作的demo完成。

结尾

​ 下一篇应该是wxWidgets的日志系统的拦截和重定向,把产生的日志全部拦截,记录到数据库中,供排查错误使用。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值