MFC创建用户线程,直接关闭程序时,线程就报错了.怎么让它安全退出
MFC创建用户线程,直接关闭程序时,线程就报错了.如何让它安全退出?
我创建了一个MFC的对话框程序,有个按扭事件创建了一个线程。线程的功能是进行一个很耗时的计算,
这个线程要能支持暂停和停止功能。而且线程中的计算过程,数据需要实时的展示到界面上。
代码很简单的,
就是一个按扭控制线程的创建和结束,
另一个按扭控制线程的暂停和继续,
线程计算出来的数据发消息通知另一函数更新到界面上展示。
线程创建和执行计算,以及实时展示总体是这样子的:
现在遇到一个问题,就是如果线程还在循环运行着,用户直接关闭程序,程序退出时会报错。要如何避免这样的错误发生呢?
或者说想进行这种类型的计算和控制,线程应该如何设计?
补充:我在OnClose()中将m_bStartCalc置成FALSE,然后 Sleep一下,还是会报错。 或者调用Wait
祝大家十一快乐。
------解决思路----------------------
MDI工程的主框架关闭是,是不会调用view类的onClose事件的,
只会调用主框架的onclose事件,应该在主框架的onclose中来清理view类的资源。
dialog工程不报错是因为dialog工程关闭时,会调用自己的onclose事件,而你在onclose事件中已经处理过了资源。所以不会出错了。
我创建了一个MFC的对话框程序,有个按扭事件创建了一个线程。线程的功能是进行一个很耗时的计算,
这个线程要能支持暂停和停止功能。而且线程中的计算过程,数据需要实时的展示到界面上。
代码很简单的,
就是一个按扭控制线程的创建和结束,
另一个按扭控制线程的暂停和继续,
线程计算出来的数据发消息通知另一函数更新到界面上展示。
线程创建和执行计算,以及实时展示总体是这样子的:
LRESULT CMainDlg::WoekerThread(LPARAM lParam)
{ //线程函数
CMainDlg* pDlg = (CMainDlg*)lParam;
pDlg->CalcData(); //调用计算模块,这样写的目的是为了简单,免得在线程里调用类成员变量和函数还得加pDlg->xxx
return 0;
}
void CMainDlg::CalcData()
{
while (m_bStartCalc)
{
m_dwCurrentVal = GetValue(); //进行计算
m_SomeOtherData = xxxxxxx; //一些其他计算,更新另外一部分成员变量的值
SendMessage(UM_UPDATEPROCESS); //发消息通知主线程要更新展示数据,由消息函数UpdateProcess处理这个消息
//没有用PostMessage的目的是因为我计算时需要使用类成员变量,数据展示也需要使用类成员变量,以免冲突
WaitForSingleObject(m_hPuaseEvent, INFINITE); //这个事件用来控制线程暂停
}
m_bStartCalc = FALSE;
}
LRESULT CMainDlg::UpdateProcess(WPARAM wParam, LPARAM lParam)
{ //更新展示信息的消息函数
CString strCurVal;
strCurVal.Format(_T("当前计算值:%u"), m_dwCurrentVal);
SetDlgItemText(IDD_STATIC_PROCESS, strCurVal);
UpdateData(FALSE); //有一些控件绑定了控件变量,在线程中改变那些变量值后,直接用UpdateData来更新
}
void CMainDlg::OnStartBtn()
{//线程启动和停止按扭事件
if (m_bStartCalc)
{//说明线程已经在运行中,将m_bStartCalc置成FALSE,让线程的循环退出
m_bStartCalc = FALSE;
if (m_hPuaseEvent && m_bPause)//线程是暂停状态的话,要将事件置成有信号状态,让线程运行起来
{//避免线程一直是等待事件暂停状态,就不能退出了
SendEvent(m_hPuaseEvent);
}
SetDlgItemText(IDB_BTN_START, _T("开始"));
}
else
{
if (m_hPuaseEvent == NULL)
{//通过事件来控制线程暂停
m_hPuaseEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
}
m_bStartCalc = TRUE;
m_pWinThread = AfxBeginThread((AFX_THREADPROC)WoekerThread, this, THREAD_PRIORITY_HIGHEST, CREATE_SUSPENDED);
m_pWinThread->m_bAutoDelete = FALSE;
m_pWinThread->ResumeThread();
SetDlgItemText(IDB_BTN_START, _T("停止"));
}
}
void CMainDlg::OnPauseBtn()
{//线程暂停和继续按扭事件
if (m_pWinThread)
{
if (m_bPause)
{
SendEvent(m_hPuaseEvent); //如果是暂停状态,将事件置成有信号,让线程内的循环继续运行机制
m_bPause = FALSE;
SetDlgItemText(IDB_BTN_PAUSE, _T("暂停"));
}
else
{
m_bPause = TRUE;
ResetEvent(m_hPuaseEvent);
SetDlgItemText(IDB_BTN_PAUSE, _T("继续"));
}
}
}
void CMainDlg::OnClose()
{
if (m_bStartCalc)
{//这个方法也会抱错,为什么呢?
m_bStartCalc = FALSE;
Sleep(1000);
}
if (m_pWinThread && m_bStartCalc )
{//这个也会抱错
m_bStartCalc = FALSE;
WaitForSingleObject(m_pWinThread->m_hThread, 1000);
}
CDialog::OnClose();
}
现在遇到一个问题,就是如果线程还在循环运行着,用户直接关闭程序,程序退出时会报错。要如何避免这样的错误发生呢?
或者说想进行这种类型的计算和控制,线程应该如何设计?
补充:我在OnClose()中将m_bStartCalc置成FALSE,然后 Sleep一下,还是会报错。 或者调用Wait
祝大家十一快乐。
------解决思路----------------------
MDI工程的主框架关闭是,是不会调用view类的onClose事件的,
只会调用主框架的onclose事件,应该在主框架的onclose中来清理view类的资源。
dialog工程不报错是因为dialog工程关闭时,会调用自己的onclose事件,而你在onclose事件中已经处理过了资源。所以不会出错了。