一、先来看个简单的例子:
新建MyThread,继承wxThread
#pragma once #include <wx/dialog.h> #include <wx/thread.h> #include <wx/event.h> wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent); wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent); // 为线程事件传输数据,你可以定义成其他的结构 typedef struct THREAD_MSG { DWORD threadId; wxString info; } THREAD_MSG_TYPE; class MyThread : public wxThread { public: MyThread(wxDialog* handler); ~MyThread(); virtual void * Entry() override; void SendMsgToDialog(const wxEventType & evtType, const wxString& msg); protected: wxDialog * m_handler; };#include "MyThread.h" wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent); wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent); MyThread::MyThread(wxDialog* handler) { m_handler = handler; } MyThread::~MyThread() { } void * MyThread::Entry() { if (!TestDestroy()) { SendMsgToDialog(wxEVT_COMMAND_MYTHREAD_UPDATE, wxT("Thread is running!")); // ... } SendMsgToDialog(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxT("Thread is over!")); return 0; } void MyThread::SendMsgToDialog(const wxEventType & evtType,const wxString& msg) { wxThreadEvent * threadEvt = new wxThreadEvent(evtType); THREAD_MSG_TYPE * threadMsg = new THREAD_MSG_TYPE{ wxThread::GetCurrentId(),msg }; threadEvt->SetExtraLong(reinterpret_cast<long>(threadMsg)); wxQueueEvent(m_handler, threadEvt); }
在对话框MyDialog中调用如下:
#pragma once #include "GUI.h" #include <wx/msgdlg.h> #include "MyThread.h" class MyDialog :public MainDialog { public: MyDialog(wxDialog * dlg) :MainDialog(dlg) {} ~MyDialog() {} void OnThreadUpdate(wxCommandEvent& evt); void OnThreadCompletion(wxCommandEvent& evt); void OnStart(wxCommandEvent& event); protected: MyThread * pThread; wxDECLARE_EVENT_TABLE(); };#include "MyDialog.h" #include "vld.h" wxBEGIN_EVENT_TABLE(MyDialog, MainDialog) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyDialog::OnThreadUpdate) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_COMPLETED, MyDialog::OnThreadCompletion) wxEND_EVENT_TABLE() void MyDialog::OnThreadUpdate(wxCommandEvent& evt) { wxThreadEvent* tEvt = (wxThreadEvent*)&evt; THREAD_MSG_TYPE * threadMsg = (THREAD_MSG_TYPE *)tEvt->GetExtraLong(); wxString msg = wxString::Format(wxT("线程Id:%x,发来消息:%s\r\n"), threadMsg->threadId, threadMsg->info); OutputDebugString(msg); delete threadMsg; } void MyDialog::OnThreadCompletion(wxCommandEvent& evt) { wxThreadEvent* tEvt = (wxThreadEvent*)&evt; THREAD_MSG_TYPE * threadMsg = (THREAD_MSG_TYPE *)tEvt->GetExtraLong(); wxString msg = wxString::Format(wxT("线程Id:%x,发来消息:%s\r\n"), threadMsg->threadId, threadMsg->info); OutputDebugString(msg); delete threadMsg; pThread = nullptr; } void MyDialog::OnStart(wxCommandEvent& event) { pThread = new MyThread(this); pThread->Run(); }
二、线程类wxThread
1、创建线程,指定线程是detach还是join,join需要等待,detach立即返回
MyThread::MyThread(wxDialog* handler):wxThread(wxTHREAD_DETACHED) { m_handler = handler; }可以通过GetKind函数判断是哪种线程
2、需不需要调用create函数
一般情况下,不需要调用create函数,因为在run中会调用一次
pThread = new MyThread(this); if (pThread->Run() != wxTHREAD_NO_ERROR) { wxLogError(wxT("Thread create error.")); }
pThread->Pause(); pThread->Resume(); pThread->Kill();
可以通过IsAlive来判断线程是否还活着
pThread->SetPriority(wxPRIORITY_MAX);
wxThread::Sleep(1000); wxThread::Yield();
三、线程同步
1、wxMutex互斥量,某个时刻,多个线程只能有一个拥有这个互斥量
wxMutex m_mutex; wxMutexLocker lock(m_mutex);2、wxCriticalSection关键区域。某个时刻,多个线程只能有一个执行关键区域的代码wxCriticalSection cs; cs.Enter(); // ... cs.Leave();3、wxSemaphore信号量,初始时,可以设置起始信号数,和最大的信号数wxSemaphore semaphore(2,10); semaphore.Wait(); // ... semaphore.Post();4、wxCondition条件变量,一般用在生产者消费者模式中// 创建一个条件变量 wxCondition condition(m_mutex); // 让条件变量处于等待状态 condition.Wait(); condition.WaitTimeout(1000); // 通知所有线程中的条件变量,有信号了 condition.Broadcast(); // 通知最多一个线程的条件变量,有信号了 condition.Signal();
四、定时器wxTimer
1、创建一个定时器
#define TIMER_ID 1000 wxTimer m_timer(this, TIMER_ID); // 事件 EVT_TIMER(TIMER_ID, MyDialog::OnTimer)2、开始与停止m_timer.StartOnce(2000); m_timer.Start(2000); m_timer.Stop();
五、空闲时间,当CPU处于空闲的时候会执行
1、设置空间时间处理事件
EVT_IDLE(MyDialog::OnMyIdle)2、事件处理函数void OnMyIdle(wxIdleEvent& event);3、判断事情有没有处理完,没有则再次请求if (!FinishedIdleTask()) { event.RequestMore(); } event.Skip();