简单的多线程实例

时间:2022-09-24 18:21:07



 

    平时在MFC里使用多线程时其实是很方面的,因为微软提供了一个API让我们很方面的去创建线程:下面是MSDN中关于CreateThread的函数原型:

 

1、函数原型声明:

 

 

[cpp] view plaincopyprint?
  1. CreateThread  
  2.   
  3. The CreateThread function creates a thread to execute within the virtual address space of the calling process.  
  4.   
  5. To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function.  
  6.   
  7.   
  8. HANDLE CreateThread(  
  9.   LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  10.   SIZE_T dwStackSize,  
  11.   LPTHREAD_START_ROUTINE lpStartAddress,  
  12.   LPVOID lpParameter,  
  13.   DWORD dwCreationFlags,  
  14.   LPDWORD lpThreadId  
  15. );  

 

 

2、参数说明:

[cpp] view plaincopyprint?
  1. lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。  
  2.   
  3.   
  4. dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。  
  5.   
  6.   
  7. lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:  
  8.   
  9.   
  10. DWORD WINAPI ThreadProc (LPVOID pParam) ,格式不正确将无法调用成功。   
  11.   
  12.   
  13. lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。   
  14.   
  15.   
  16. dwCreationFlags :线程标志,可取值如下   
  17.   
  18.   
  19. CREATE_SUSPENDED: 创建一个挂起的线程   
  20.   
  21.   
  22. 0 :创建后立即激活。   
  23.   
  24.   
  25. lpThreadId:保存新线程的id。  

 

 

3、返回值:

  函数成功,返回线程句柄;函数失败返回false。

4、实例代码:

 

  A、新建一个对话框工程为MFC,在MFCDlg.h添加两个成员函数,注意一定要是静态的,代码如下:

 

[cpp] view plaincopyprint?
  1. /////////////////////////////////////////////////////////////////////////////  
  2. // CMFCDlg dialog  
  3.   
  4. class CMFCDlg : public CDialog  
  5. {  
  6. // Construction  
  7. public:  
  8.     CMFCDlg(CWnd* pParent = NULL);  // standard constructor  
  9.   
  10.     // 线程B1、B2函数  
  11.     static DWORD WINAPI ThreadB1(LPVOID lpParam);  
  12.     static DWORD WINAPI ThreadB2(LPVOID lpParam);  
  13.   
  14.     ......  
  15. }  

 

  B、在cpp文件中实现函数,添加代码如下:

 

[cpp] view plaincopyprint?
  1. DWORD WINAPI CMFCDlg::ThreadB1(LPVOID lpParam)       
  2. {  
  3.     // 定义结构对象  
  4.     PROCESS_INFORMATION pi;  
  5.     STARTUPINFO         si;  
  6.     BOOL                bRet;  
  7.   
  8.     // 申请空间  
  9.     ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  
  10.     ZeroMemory(&si,sizeof(STARTUPINFO));  
  11.       
  12.     // 设置进程启动属性  
  13.     si.cb           =   sizeof(STARTUPINFO);  
  14.     si.lpReserved   =   NULL;  
  15.     si.lpDesktop    =   NULL;  
  16.     si.lpTitle      =   NULL;  
  17.     si.dwFlags      =   STARTF_USESHOWWINDOW;  
  18.     si.wShowWindow  =   SW_SHOWNORMAL;  
  19.     si.cbReserved2  =   NULL;  
  20.     si.lpReserved2  =   NULL;  
  21.       
  22.     bRet = CreateProcess(_T("C://Program Files//Internet Explorer//IEXPLORE.exe"),  
  23.                          _T("http://www.coderfans.cn"),  
  24.                          NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);  
  25.     return 0;  
  26. }  
  27.   
  28. DWORD WINAPI CMFCDlg::ThreadB2(LPVOID lpParam)       
  29. {  
  30.     // 定义结构对象  
  31.     PROCESS_INFORMATION pi;  
  32.     STARTUPINFO         si;  
  33.     BOOL                bRet;  
  34.       
  35.     // 申请空间  
  36.     ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  
  37.     ZeroMemory(&si,sizeof(STARTUPINFO));  
  38.       
  39.     // 设置进程启动属性  
  40.     si.cb           =   sizeof(STARTUPINFO);  
  41.     si.lpReserved   =   NULL;  
  42.     si.lpDesktop    =   NULL;  
  43.     si.lpTitle      =   NULL;  
  44.     si.dwFlags      =   STARTF_USESHOWWINDOW;  
  45.     si.wShowWindow  =   SW_SHOWNORMAL;  
  46.     si.cbReserved2  =   NULL;  
  47.     si.lpReserved2  =   NULL;  
  48.       
  49.     bRet = CreateProcess(_T("C://Program Files//Internet Explorer//IEXPLORE.exe"),  
  50.                          _T("http://blog.csdn.net/wangningyu"),  
  51.                          NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);  
  52.   
  53.     return 0;  
  54. }  

 

  C、然后在对话框初始化时创建进程即可,代码如下:

 

[cpp] view plaincopyprint?
  1. BOOL CMFCDlg::OnInitDialog()  
  2. {  
  3.     CDialog::OnInitDialog();  
  4.     ......  
  5.   
  6.     // Set the icon for this dialog.  The framework does this automatically  
  7.     //  when the application's main window is not a dialog  
  8.     SetIcon(m_hIcon, TRUE);         // Set big icon  
  9.     SetIcon(m_hIcon, FALSE);        // Set small icon  
  10.       
  11.     // TODO: Add extra initialization here  
  12.     DWORD   dw1,dw2;  
  13.     CreateThread(NULL,0,ThreadB1,NULL,0,&dw1);  
  14.     Sleep(100);  
  15.   
  16.     CreateThread(NULL,0,ThreadB2,NULL,0,&dw2);  
  17.     Sleep(100);  
  18.     return TRUE;  // return TRUE  unless you set the focus to a control  
  19. }  

 

5、MFC创建多线程完成,就这么简单咯!

 

    平时在MFC里使用多线程时其实是很方面的,因为微软提供了一个API让我们很方面的去创建线程:下面是MSDN中关于CreateThread的函数原型:

 

1、函数原型声明:

 

 

[cpp] view plaincopyprint?
  1. CreateThread  
  2.   
  3. The CreateThread function creates a thread to execute within the virtual address space of the calling process.  
  4.   
  5. To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function.  
  6.   
  7.   
  8. HANDLE CreateThread(  
  9.   LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  10.   SIZE_T dwStackSize,  
  11.   LPTHREAD_START_ROUTINE lpStartAddress,  
  12.   LPVOID lpParameter,  
  13.   DWORD dwCreationFlags,  
  14.   LPDWORD lpThreadId  
  15. );  

 

 

2、参数说明:

[cpp] view plaincopyprint?
  1. lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。  
  2.   
  3.   
  4. dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。  
  5.   
  6.   
  7. lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:  
  8.   
  9.   
  10. DWORD WINAPI ThreadProc (LPVOID pParam) ,格式不正确将无法调用成功。   
  11.   
  12.   
  13. lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。   
  14.   
  15.   
  16. dwCreationFlags :线程标志,可取值如下   
  17.   
  18.   
  19. CREATE_SUSPENDED: 创建一个挂起的线程   
  20.   
  21.   
  22. 0 :创建后立即激活。   
  23.   
  24.   
  25. lpThreadId:保存新线程的id。  

 

 

3、返回值:

  函数成功,返回线程句柄;函数失败返回false。

4、实例代码:

 

  A、新建一个对话框工程为MFC,在MFCDlg.h添加两个成员函数,注意一定要是静态的,代码如下:

 

[cpp] view plaincopyprint?
  1. /////////////////////////////////////////////////////////////////////////////  
  2. // CMFCDlg dialog  
  3.   
  4. class CMFCDlg : public CDialog  
  5. {  
  6. // Construction  
  7. public:  
  8.     CMFCDlg(CWnd* pParent = NULL);  // standard constructor  
  9.   
  10.     // 线程B1、B2函数  
  11.     static DWORD WINAPI ThreadB1(LPVOID lpParam);  
  12.     static DWORD WINAPI ThreadB2(LPVOID lpParam);  
  13.   
  14.     ......  
  15. }  

 

  B、在cpp文件中实现函数,添加代码如下:

 

[cpp] view plaincopyprint?
  1. DWORD WINAPI CMFCDlg::ThreadB1(LPVOID lpParam)       
  2. {  
  3.     // 定义结构对象  
  4.     PROCESS_INFORMATION pi;  
  5.     STARTUPINFO         si;  
  6.     BOOL                bRet;  
  7.   
  8.     // 申请空间  
  9.     ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  
  10.     ZeroMemory(&si,sizeof(STARTUPINFO));  
  11.       
  12.     // 设置进程启动属性  
  13.     si.cb           =   sizeof(STARTUPINFO);  
  14.     si.lpReserved   =   NULL;  
  15.     si.lpDesktop    =   NULL;  
  16.     si.lpTitle      =   NULL;  
  17.     si.dwFlags      =   STARTF_USESHOWWINDOW;  
  18.     si.wShowWindow  =   SW_SHOWNORMAL;  
  19.     si.cbReserved2  =   NULL;  
  20.     si.lpReserved2  =   NULL;  
  21.       
  22.     bRet = CreateProcess(_T("C://Program Files//Internet Explorer//IEXPLORE.exe"),  
  23.                          _T("http://www.coderfans.cn"),  
  24.                          NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);  
  25.     return 0;  
  26. }  
  27.   
  28. DWORD WINAPI CMFCDlg::ThreadB2(LPVOID lpParam)       
  29. {  
  30.     // 定义结构对象  
  31.     PROCESS_INFORMATION pi;  
  32.     STARTUPINFO         si;  
  33.     BOOL                bRet;  
  34.       
  35.     // 申请空间  
  36.     ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  
  37.     ZeroMemory(&si,sizeof(STARTUPINFO));  
  38.       
  39.     // 设置进程启动属性  
  40.     si.cb           =   sizeof(STARTUPINFO);  
  41.     si.lpReserved   =   NULL;  
  42.     si.lpDesktop    =   NULL;  
  43.     si.lpTitle      =   NULL;  
  44.     si.dwFlags      =   STARTF_USESHOWWINDOW;  
  45.     si.wShowWindow  =   SW_SHOWNORMAL;  
  46.     si.cbReserved2  =   NULL;  
  47.     si.lpReserved2  =   NULL;  
  48.       
  49.     bRet = CreateProcess(_T("C://Program Files//Internet Explorer//IEXPLORE.exe"),  
  50.                          _T("http://blog.csdn.net/wangningyu"),  
  51.                          NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);  
  52.   
  53.     return 0;  
  54. }  

 

  C、然后在对话框初始化时创建进程即可,代码如下:

 

[cpp] view plaincopyprint?
  1. BOOL CMFCDlg::OnInitDialog()  
  2. {  
  3.     CDialog::OnInitDialog();  
  4.     ......  
  5.   
  6.     // Set the icon for this dialog.  The framework does this automatically  
  7.     //  when the application's main window is not a dialog  
  8.     SetIcon(m_hIcon, TRUE);         // Set big icon  
  9.     SetIcon(m_hIcon, FALSE);        // Set small icon  
  10.       
  11.     // TODO: Add extra initialization here  
  12.     DWORD   dw1,dw2;  
  13.     CreateThread(NULL,0,ThreadB1,NULL,0,&dw1);  
  14.     Sleep(100);  
  15.   
  16.     CreateThread(NULL,0,ThreadB2,NULL,0,&dw2);  
  17.     Sleep(100);  
  18.     return TRUE;  // return TRUE  unless you set the focus to a control  
  19. }  

 

5、MFC创建多线程完成,就这么简单咯!

===========================================================================================

实例:

DWORD WINAPI CTingDlg::ThreadB2(LPVOID lpParam)       
{
Sleep(1500);
char buf[128];
//use mciSendCommand
MCI_OPEN_PARMS mciOpen;
MCIERROR mciError;
//mciOpen.lpstrDeviceType = "avivideo"; //*.avi
mciOpen.lpstrDeviceType = "mpegvideo";
mciOpen.lpstrElementName = "resource\\music.mp3";
mciError = mciSendCommand(3,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_ELEMENT ,(DWORD)&mciOpen);
if(mciError)
{
mciGetErrorString(mciError,buf,128);
// MessageBox("send MCI_PLAY command failed", "ERROR");
return 0;
}
UINT DeviceID = mciOpen.wDeviceID ;
MCI_PLAY_PARMS mciPlay;
mciError = mciSendCommand(DeviceID, MCI_PLAY, MCI_DGV_PLAY_REPEAT,
(DWORD) (LPMCI_PLAY_PARMS)&mciPlay); //MCI_DGV_PLAY_REPEAT, 要 #include "Digitalv.h"
if(mciError)
{
mciGetErrorString(mciError,buf,128);
return 0;
}
return 0;
}

=========================================================================================

创建线程时,线程函数如果要设置成类的成员函数,则必须是静态成员函数,在此函数中不能使用非静态成员变量,如果要使用非静态成员变量,则一种比较适合线程的方法是:建立线程的时候把this作为CreateThread的一个参数(即第4个参数,就是那个LPVOID型的),然后线程里就对应pParam,例如:

        static UINT ThreadProc(LPVOID pParam)   
        { 
       Your_Class *p=(Your_Class *)pParam;   
                //然后用p间接使用成员变量。 
         }