您发布的代码存在一些严重问题。在你做更多事情之前,它们需要被修复。
工作线程是一个“忙循环”。它将消耗所有可用的 CPU 周期并使其他任何事情(例如运行 GUI)变得缓慢且无响应。我建议在 while 循环中添加对 Sleep() 的调用,作为快速修复。
主线程和工作线程都尝试同时访问计数器变量。你运行这个足够长的时间,它会崩溃。您应该使用互斥锁或等效物保护计数器。
让我们稍微重新设计一下,然后移植到 wxWidgets。我们会需要
A. 一个工作线程,它每秒(大约)将计数器递增 10 次(大约)并在其余时间休眠,以便我们可以更新 GUI
B. 每秒检查和显示计数器值两次的 GUI 线程
C. GUI 线程还将监视键盘并在按下“q”时停止计数器。
D. 我们将使用wxThreadHelper类来管理我们的线程。
关键实现细节如下
定义主框架,包括所有 wxThreadHelper 的优点
class MyFrame : public wxFrame, public wxThreadHelper
{
public:
MyFrame(const wxString& title);
// worker thread entry point
wxThread::ExitCode Entry();
// keyboard monitor
void OnChar(wxKeyEvent& event );
// display updater
void OnTimer(wxTimerEvent& event);
private:
// the counter
unsigned int mCounter;
// protect the counter from access by both threads at once
wxCriticalSection mCS;
// display update timer
wxTimer * mTimer;
DECLARE_EVENT_TABLE()
};
注意键盘和计时器事件
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_CHAR(MyFrame::OnChar)
EVT_TIMER(-1,MyFrame::OnTimer)
END_EVENT_TABLE()
构建框架
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title)
, mCounter( 0 )
{
// set the frame icon
SetIcon(wxICON(sample));
CreateStatusBar(2);
SetStatusText("Welcome to Asynchronous Counter!");
// Create thread and start it going
CreateThread();
GetThread()->Run();
// Create update timer and start it going
mTimer = new wxTimer(this);
mTimer->Start(500);
}
工作线程每秒递增计数器 10 次
wxThread::ExitCode MyFrame::Entry()
{
// loop, so long as we haven't been asked to quit
while ( ! GetThread()->TestDestroy()) {
{
// increment counter, to a maximum value
wxCriticalSectionLocker lock( mCS );
if( mCounter >= 0xFFFFFFFF )
break;
++mCounter;
}
// Let other things happen for 1/10 second
Sleep(100);
}
// Counter is finished, or we have been asked to stop
return (wxThread::ExitCode)0;
}
监控键盘以获取退出请求
void MyFrame::OnChar(wxKeyEvent& event )
{
event.Skip();
if( event.GetKeyCode() == (int) 'q' )
GetThread()->Delete();
}
定时器触发时更新显示
void MyFrame::OnTimer(wxTimerEvent& )
{
unsigned int current_counter_value;
{
wxCriticalSectionLocker lock( mCS );
current_counter_value = mCounter;
}
SetStatusText(wxString::Format("Counter = %d",current_counter_value));
}