• C++/MFC中多线程使用


    一。创建线程的三种方式

    1.CreateThread (windows中vc++)

    CreateThread(
        _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程属性
        _In_ SIZE_T dwStackSize, //栈空间大小
        _In_ LPTHREAD_START_ROUTINE lpStartAddress, //线程执行函数地址
        _In_opt_ __drv_aliasesMem LPVOID lpParameter, //传递参数
        _In_ DWORD dwCreationFlags, //标志,可以选择挂起
        _Out_opt_ LPDWORD lpThreadId //线程id
        );
     1 DWORD WINAPI ThreadProc(LPVOID lpParameter)
     2 {
     3     int a = (int)lpParameter;
     4     CString str;
     5     str.Format(_T("%d"),a);
     6     AfxMessageBox(str);
     7     return 0;
     8 }
     9 void CSegDlg::OnBnClickedstop()
    10 {
    11     // TODO: 在此添加控件通知处理程序代码
    12     DWORD dwThreadId = 0; //线程id
    13     HANDLE hThread=CreateThread(NULL, 0, ThreadProc, (LPVOID)123, 0, &dwThreadId); //返回线程句柄
    14     //关闭句柄,线程结束后释放
    15     CloseHandle(hThread);
    16 }

    2.AfxBeginThread(MFC)

    CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
    	int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0,
    	DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);  //创建工作线程,工作线程用来处理一些逻辑
    CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL); //创建界面线程,界面线程会有消息循环
     1 UINT _cdecl ThreadProc(LPVOID lpParameter)
     2 {
     3     int a = (int)lpParameter;
     4     CString str;
     5     str.Format(_T("%d"), a);
     6     AfxMessageBox(str);
     7     return 0;
     8 }
     9 void CSegDlg::OnBnClickedstop()
    10 {
    11     // TODO: 在此添加控件通知处理程序代码
    12     CWinThread *pThread=AfxBeginThread(ThreadProc, (LPVOID)456);
    13 
    14 }

     3._beginthread

    二。子线程使用主线程参数

    1.子线程对应于一个普通函数,不能被简单的声明成主对话框类的成员函数,因此不能使用主对话框(主线程)的参数,需要在创建线程时,将主对话框类对象的指针传递给子线程。子线程通过指针去访问主线程的变量。

     1 UINT _cdecl ThreadProc(LPVOID lpParameter)
     2 {
     3     CSegDlg* pSegDlg = (CSegDlg *)lpParameter; //转换为主对话框类的指针
     4     int a = pSegDlg->num;
     5     CString str;
     6     str.Format(_T("%d"), a);
     7     AfxMessageBox(str);
     8     return 0;
     9 }
    10 void CSegDlg::OnBnClickedstop()
    11 {
    12     num = 100; //成员变量
    13     CWinThread *pThread=AfxBeginThread(ThreadProc, this);
    14 }

     2.如果一定要将子线程函数声明为类成员函数,需要定义为静态成员函数

     1 UINT _cdecl CSegDlg::ThreadProc(LPVOID lpParameter) //static函数
     2 {
     3     CSegDlg* pSegDlg = (CSegDlg *)lpParameter; //仍然需要传递对象指针,因为static关键词没有this指针
     4     int a = pSegDlg->num;  
     5     CString str;
     6     str.Format(_T("%d"), a);
     7     AfxMessageBox(str);
     8     return 0;
     9 }
    10 void CSegDlg::OnBnClickedstop()
    11 {
    12     num = 100;
    13     CWinThread *pThread=AfxBeginThread(ThreadProc, this);
    14 }

    三。创建界面线程。

    1.如同主对话框创建时一样,会有一个应用程序类App,如果需要再创建一个线程来管理对话框,需要创建自定义类,继承于CWinThread类。

    2.创建好的App类和对话框类如下图所示。

     需要在CUIThreadApp中添加CTestDlg.h

    3.重写CUIThreadApp中的InitInstance()和ExitInstance()函数。进行对话框的创建和资源的释放。

     1 BOOL CUIThreadApp::InitInstance()
     2 {
     3     // TODO:    在此执行任意逐线程初始化
     4     /*CTestDlg dlg;  //创建模态对话框
     5     dlg.DoModal(); //阻塞
     6     return FALSE; //return FALSE会释放线程
     7     */
     8 
     9 
    10     CTestDlg* dlg = new CTestDlg();
    11     dlg->Create(IDD_DIALOG1);
    12     dlg->ShowWindow(SW_SHOW);
    13     dlg->RunModalLoop();  // 让非模态对话框处于循环
    14     return FALSE; //return FALSE释放线程
    15 }

    4.在对话框对象中进行界面线程的创建。

    1 void CmfcThreadDlg::OnBnClickedOk()
    2 {
    3     // TODO: 在此添加控件通知处理程序代码
    4     AfxBeginThread(RUNTIME_CLASS(CUIThreadApp));
    5 }

    四。线程挂起(暂停)、恢复、中止

    1.SuspendThread

    DWORD
    WINAPI
    SuspendThread(
    _In_ HANDLE hThread
    );

    2.ResumeThread

    DWORD
    WINAPI
    ResumeThread(
    _In_ HANDLE hThread
    );

     1 HANDLE hThread;
     2 void CmfcThreadDlg::OnBnClickedOk()
     3 {
     4     CWinThread* pThread = AfxBeginThread(ThreadProc, this);
     5     hThread = pThread->m_hThread; //获取线程句柄
     6 }
     7 
     8 void CmfcThreadDlg::OnBnClickedbtnsuspend()
     9 {
    10     SuspendThread(hThread);
    11 }
    12 
    13 void CmfcThreadDlg::OnBnClickedbtnresume()
    14 {
    15     ResumeThread(hThread);
    16 }

    3.线程退出

  • 相关阅读:
    LeetCode链表解题模板
    c++中的new、operator new、placement new
    树的前序、中序、后续、层次遍历的递归和非递归解法
    c++Volatile关键词
    南大算法设计与分析课程OJ答案代码(5)--割点与桥和任务调度问题
    c++右值引用以及使用
    c++选择重载函数
    从4行代码看右值引用
    被遗忘的C结构体打包技术
    南大算法设计与分析课程OJ答案代码(4)--变位词、三数之和
  • 原文地址:https://www.cnblogs.com/sclu/p/11635082.html
Copyright © 2020-2023  润新知