大家好,我使用多线程编程时有些问题一直没有搞明白,如下
1.使用我下面这段代码创建用户界面线程是否正确。
2.创建的线程结束后,如何通知主线程?
3.我的这个线程pMyThread需要重复使用,是否每次重新使用都是使用AfxBeginThread来创建,像我下面这样的做法?
4.因为创建的线程只有一个,并且主线程和创建的线程不会同时去操纵同一数据,所以是否可以不需关注线程同步的问题?
请高手给予解答,非常感谢!
CMyThread * pMyThread;
threadInfo Info ;//向线程传递的结构体参数
void CMyDlg::OnBtnStart() //启用及关闭线程的按钮
{ bool bCreateThread=FALSE;
if (pMyThread ==NULL)
{ bCreateThread=TRUE;
}else
{ GetExitCodeThread(pMyThread->m_hThread, &pMyThread->m_nThreadID);
if ( pMyThread->m_nThreadID==0x103) //检查线程是否在运行,如果是就停止运行
{ Info.RunState=IsStop;
return ;
}else bCreateThread=TRUE;
} if (bCreateThread)
{ //创建线程,是否每次重新创建都是使用AfxBeginThread来创建?这样做是否有资源没有释放?
if(!(pMyThread = (CMyThread*)AfxBeginThread(RUNTIME_CLASS(CMyThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED)))
{ AfxMessageBox(_T( "创建线程失败 "));
return ;
}
Info.RunState=IsRun;
Info.obj=this->obj; //一个类对象
Info.myDlgHandle =this; //在线程中需要控制主线程对话框中的控件,所以在这里传递进去窗体的句柄
pMyThread->m_pThreadParams =&Info;//Info是我定义的一个结构体对象,在这里使用这种方式传递
pMyThread-> ResumeThread(); //真正开始执行线程
}
}CMyThread::CMyThread()
{ m_bAutoDelete = TRUE; }int CMyThread::Run()
{
ASSERT_VALID(this);
threadInfo *Info =(threadInfo*)this->m_pThreadParams;
CMyDlg * myDlg =(CMyDlg *) Info->myDlgHandle );
CProgressCtrl * m_Progress=&myDlg ->m_Progress;
CMSHFlexGrid * m_Grid= &myDlg->m_Grid; for ( int i=0;i< m_Grid->GetRows()-1;i++)
{
if ( Info->RunState==IsStop)break;//在主线程中控制是否中止线程
m_Grid->SetRow(i);
/*Info->obj.DoWorkFunction为一个需要很长的工作时间的函数,在调用时可能会有错误产生,需要弹出一个对话框,
根据用户对对话框的选择而做出是否退出线程,因为有对话框,所以需要创建用户界面线程*/
if (!Info->obj.DoWorkFunction())
{ break;
}
//操纵主线程对话框的进度条
m_Progress->SetPos(((double(i))/(double)m_Grid->GetRows()*100);
}
ExitInstance();
return 0;
//另外当线程结束后,我如何通知主线程? 现在我的做法是使用一个计时器在那检查线程的状态,这样做是否正确?
}
1.使用我下面这段代码创建用户界面线程是否正确。
2.创建的线程结束后,如何通知主线程?
3.我的这个线程pMyThread需要重复使用,是否每次重新使用都是使用AfxBeginThread来创建,像我下面这样的做法?
4.因为创建的线程只有一个,并且主线程和创建的线程不会同时去操纵同一数据,所以是否可以不需关注线程同步的问题?
请高手给予解答,非常感谢!
CMyThread * pMyThread;
threadInfo Info ;//向线程传递的结构体参数
void CMyDlg::OnBtnStart() //启用及关闭线程的按钮
{ bool bCreateThread=FALSE;
if (pMyThread ==NULL)
{ bCreateThread=TRUE;
}else
{ GetExitCodeThread(pMyThread->m_hThread, &pMyThread->m_nThreadID);
if ( pMyThread->m_nThreadID==0x103) //检查线程是否在运行,如果是就停止运行
{ Info.RunState=IsStop;
return ;
}else bCreateThread=TRUE;
} if (bCreateThread)
{ //创建线程,是否每次重新创建都是使用AfxBeginThread来创建?这样做是否有资源没有释放?
if(!(pMyThread = (CMyThread*)AfxBeginThread(RUNTIME_CLASS(CMyThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED)))
{ AfxMessageBox(_T( "创建线程失败 "));
return ;
}
Info.RunState=IsRun;
Info.obj=this->obj; //一个类对象
Info.myDlgHandle =this; //在线程中需要控制主线程对话框中的控件,所以在这里传递进去窗体的句柄
pMyThread->m_pThreadParams =&Info;//Info是我定义的一个结构体对象,在这里使用这种方式传递
pMyThread-> ResumeThread(); //真正开始执行线程
}
}CMyThread::CMyThread()
{ m_bAutoDelete = TRUE; }int CMyThread::Run()
{
ASSERT_VALID(this);
threadInfo *Info =(threadInfo*)this->m_pThreadParams;
CMyDlg * myDlg =(CMyDlg *) Info->myDlgHandle );
CProgressCtrl * m_Progress=&myDlg ->m_Progress;
CMSHFlexGrid * m_Grid= &myDlg->m_Grid; for ( int i=0;i< m_Grid->GetRows()-1;i++)
{
if ( Info->RunState==IsStop)break;//在主线程中控制是否中止线程
m_Grid->SetRow(i);
/*Info->obj.DoWorkFunction为一个需要很长的工作时间的函数,在调用时可能会有错误产生,需要弹出一个对话框,
根据用户对对话框的选择而做出是否退出线程,因为有对话框,所以需要创建用户界面线程*/
if (!Info->obj.DoWorkFunction())
{ break;
}
//操纵主线程对话框的进度条
m_Progress->SetPos(((double(i))/(double)m_Grid->GetRows()*100);
}
ExitInstance();
return 0;
//另外当线程结束后,我如何通知主线程? 现在我的做法是使用一个计时器在那检查线程的状态,这样做是否正确?
}
-----------------------------------------------------------------------------
CMyThread对象delete掉,CloseHandle线程句柄。
在线程中需要控制主线程对话框中的控件,所以在这里传递进去窗体的句柄
-----------------------------------------------------------------------------
不要在线程中操作主线程的界面,最好是通过发消息到主窗口,主窗口在消息响应里面操作。另外当线程结束后,我如何通知主线程? 现在我的做法是使用一个计时器在那检查线程的状态,这样做是否正确?
-----------------------------------------------------------------------------
可以检查线程句柄是否有信号来判断线程是否退出,也就是WaitForSingleObject(线程句柄),有信号就表示线程退出了。
自己看这个例子,问题也就解决了!
TO:fandh,我要创建的是一个用户界面线程,而你的例子中使用CreateThread创建的线程无法显示对话框,会出错。
TO:visualwind
1.是否是在 int CMyThread::Run() 的ExitInstance(); 后面增加 this->Delete();?2.不要在线程中操作主线程的界面,最好是通过发消息到主窗口,主窗口在消息响应里面操作。
但是m_Progress->SetPos(nPos)也不行吗?我看到fandh的例子也是这样做的啊
3.“可以检查线程句柄是否有信号来判断线程是否退出”如何做?
难道是在计时器中使用DWORD dw=WaitForSingleObjectpMyThread->m_hThread,0);
1 可以把CMyThread::m_bAutoDelete设为TRUE
2 最好发消息到主线程,否则可能会造成多线程的冲突。
3 你可以发消息来标示,在ExitInstance后面PostMessage,发自定义线程退出消息到主线程。
在我前面的代码中有将CMyThread::m_bAutoDelete设为TRUE,是否这将表示线程结束会自动释放内存?
另外我向线程传递参数时使用 pMyThread->m_pThreadParams =&Info; 是否可行?
使用PostMessage放送消息的方法非常好,我正在改用这种方法!
CMyThread::m_bAutoDelete设为TRUE表示线程在退出的时候自动delete之前创建的CMyThread对象。这样是可以的:
pMyThread->m_pThreadParams =&Info;
pMyThread-> ResumeThread();