|
This example is an example of VC++ Advanced Programming Technology and Examples Chapter 5 Multithreading
1:
Create a dialog-based program Test
2:
Place a button IDC_BT_START. and a progress bar control IDC_PROGRESS1 on the dialog
And associate a variable m_progress for IDC_PROGRESS1;
3:
In the TestDlg.h file, define a structure
struct threadInfo
{
CProgressCtrl * p_Progress;
CDialog * p_Dlg;
int second; //When the progress bar is paused
}
4:
In the TestDlg.cpp file
#define USER_PROC_FINISHED WM_USER+1
threadInfo Info;
UINT ThreadProc(LPVOID pParam)
{
threadInfo * p=(threadInfo *)pParam;
for(int i=0;i<=100;i++)
{
p->p_Progress->SetPos(i);
::Sleep(p->second*10);
}
::PostMessage(p->p_Dlg->GetSafeHwnd(),USER_PROC_FINISHED,0,0);
return 0;
}
5:
In the click response of the button IDC_BT_START:
void CTestDlg::OnBtStart()
{
To
Info.p_Progress=&m_progress;
Info.p_Dlg=this;
Info.second=1;
AfxBeginThread(ThreadProc,&Info);
}
6:
Declare the message function in TestDlg.h
To
.........
//}}AFX_MSG
afx_msg void OnFinish();
7.
In the TestDlg.cpp file
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
.......
ON_BN_CLICKED(IDC_BT_START, OnBtStart)
//}}AFX_MSG_MAP
ON_MESSAGE(USER_PROC_FINISHED,OnFinish)
END_MESSAGE_MAP()
void CTestDlg::OnFinish()
{
SetDlgItemText(IDC_BT_START,"Please restart after the thread ends");
}
In Hou Jieyi's book <Win32 Multithreaded Programming>, p294 says:
1:
MFC has a major limitation, which will affect almost everything you do. The mapping relationship between MFC objects and Win32 handles is recorded in thread local storage (TLS), so you have no way to remove an MFC object from a certain One thread is handed over to another thread, and you cannot pass MFC object pointers between threads. The pointers here include (not limited to) CWnd, CDC, CPen, CBrush, CFont, Cbitmap, CPalette... ....
2: This restriction means that you cannot put a pointer (pointing to a CWnd) into a structure, and the structure is used by a Worker thread, and you cannot give a pointer to CDialog or CView to another Threads.............Share objects between threads. Here is an inconvenient alternative. Don't place MFC objects. Change the handle of the object. You can use GetSateHwnd() to get Derived from the handle of the CWnd object, CDialog.
In the above procedures
void CTestDlg::OnBtStart()
{
To
Info.p_Progress=&m_progress; //Transfer the address of the progress bar, right?? The progress bar is derived from CWnd
Info.p_Dlg=this; //Pass the pointer of the dialog box, right?? The progress bar is derived from CWnd
Info.second=1;
AfxBeginThread(ThreadProc,&Info);
}
threadInfo Info;
UINT ThreadProc(LPVOID pParam)
{
threadInfo * p=(threadInfo *)pParam;
for(int i=0;i<=100;i++)
{
p->p_Progress->SetPos(i);//Using the address of the passed progress bar, call the member function of the progress bar, right??.
::Sleep(p->second*10);
}
::PostMessage(p->p_Dlg->GetSafeHwnd(),USER_PROC_FINISHED,0,0);
//(p->p_Dlg->GetSafeHwnd() Use the this pointer of the passed dialog box to call the member function GetSafeHwnd(), right??.
return 0;
} |
|