1 使用win32 API
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:
lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
dwStackSize:指定了线程的堆栈深度,一般都设置为0;
lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc 是线程函数名;
lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
lpThreadId:该参数返回所创建线程的ID;
如果创建成功则返回线程的句柄,否则返回NULL。
最重要的参数两个:lpStartAddress,输入函数的名称,只能是全局函数或静态函数;lpParameter,线程执行函数的参数,LPVOID类型。
其实输出函数相当于两个:句柄HANDLE型,和线程的ID。
1.1 第一个例子
线程函数是全局函数,没有参数输入,通过win32 API函数(SetDlgItemText,AfxGetMainWnd)和全局变量(m_bRun)与主进程和窗口交互。
volatile BOOL m_bRun; //volatile 修饰符的作用是告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,
//并且该值可被外部改变。
//对于多线程引用的全局变量来说,volatile 是一个非常重要的修饰符
void ThreadFunc()
{
CTime time;
CString strTime;
m_bRun=TRUE;
while(m_bRun)
{
time=CTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S");
::SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_TIME,strTime);
Sleep(1000);
}
}
void CMultiThread1Dlg::OnStart()
{
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&ThreadID);
}
void CMultiThread1Dlg::OnStop()
{
m_bRun = FALSE;
}
1.2 第二个例子
可以从主线程输入参数到线程函数,传的是地址
void ThreadFunc(int integer)
{
int i;
for(i=0;i<integer;i++)
{
Beep(200,50);
Sleep(1000);
}
}
void CMultiThread2Dlg::OnStart()
{
UpdateData(TRUE);
int integer=m_nCount;
hThread=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
(VOID*)m_nCount,
0,
&ThreadID);
GetDlgItem(IDC_START)->EnableWindow(FALSE);
WaitForSingleObject(hThread,INFINITE);
GetDlgItem(IDC_START)->EnableWindow(TRUE);
}
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
hHandle为要监视的对象(一般为同步对象,也可以是线程)的句柄;
dwMilliseconds为hHandle对象所设置的超时值,单位为毫秒;
当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态。如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。