我正在使用 wxTreeListCtrl
来显示一棵树。对于树节点的每次扩展,我都创建了一个调用后端 API 并返回响应的线程。每个线程执行后,将执行一个 HandleExpansionRequest()
,将响应元素添加到树中。这些操作工作正常。
问题是:
情况一:当线程正在执行后端函数时,同时如果用户关闭了主框架,那么在Entry()
中执行wxQueueEvent
会抛出异常。
解决这个问题:
我没有在窗口关闭时删除线程,而是使用变量 isFrameClosed
并在线程为主代码创建 wxQueueEvent
之前检查它。我的疑问是,这是在框架关闭但线程仍在执行(因为我正在创建全局 wxCriticalSection
)后停止程序崩溃的好方法吗?
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_TREELIST_ITEM_EXPANDED(wxID_ANY, MyFrame::OnItemExpand)
EVT_THREAD(ITEM_BROWSE_WORKER_EVENT,MyFrame::OnExpandThreadCompletion)
END_EVENT_TABLE()
//using below 2 variables to avoid crash when item expansion request is sent and user closes the frame.
wxCriticalSection cs_forisFrameClosed;
static bool isFrameClosed;
MyFrame::MyFrame()
{
{
wxCriticalSectionLocker lock(cs_forisFrameClosed);
isFrameClosed = false;
}
//remaining code ...
}
MyFrame::~MyFrame()
{
{
wxCriticalSectionLocker lock(cs_forisFrameClosed);
isFrameClosed = true;
}
}
void MyFrame::OnItemExpand(wxTreeListEvent& event)
{
MyThread *thread = new MyThread(this);
if (thread->Create() != wxTHREAD_NO_ERROR)
{
PrintError(__FUNCTION__, "Can't create thread!");
}
thread->Run();
}
MyThread::MyThread(MyFrame *frame) : wxThread()
{
m_frame = frame;
}
wxThread::ExitCode MyThread::Entry()
{
string resp;
GetResponseFromBackEnd(resp);
{
wxCriticalSectionLocker lock(cs_forisFrameClosed);
if (!isFrameClosed)
{
wxThreadEvent event(wxEVT_THREAD, ITEM_BROWSE_WORKER_EVENT);
event.SetString(resp);
wxQueueEvent(m_frame, event.Clone());
}
}
}
void MyFrame::OnExpandThreadCompletion(wxThreadEvent &event)
{
// this function is executed after every thread returns.
// take response from event and update tree with children.
}
最佳答案
作为the docs比方说,分离的线程会自行删除,因此您不能删除它们,因为这会导致删除两次。相反,您必须实现某种与线程通信的方式,并要求它在该执行时退出。 wxMessageQueue提供了最简单的方法之一。
关于c++ - 在wxWidgets中创建一个全局的wxCriticalSection变量不好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48249848/