【问题标题】:Win32, MFC: Ending threadsWin32,MFC:结束线程
【发布时间】:2015-08-08 03:55:09
【问题描述】:

我有一个 DLL,它有一个名为 CWork 的基于 CWinThread 的类。 我使用 AfxBeginThread 创建它。

在这个类中,我定义了一个无限循环并执行特定任务的过程。此过程将单独用作线程。我也使用 AfxBeginThread 创建它。

现在,当我的 DLL 退出时,我想结束线程。这是因为我在退出时发生了崩溃,我担心这就是原因。

另外还有

伪代码示例:

Cmain 类

Cmain::Cmain(){
    pMyThread = AfxBeginThread(CWork - a CWinThread based Class);
}

 UINT HandleNextVTSConnectionCommandProc(LPVOID pParam);

class CWork

 CWork:CWork(){
   AfxBeginThread(HandleNextVTSConnectionCommandProc, this);
 }


UINT HandleNextVTSConnectionCommandProc(LPVOID pParam){

 while(true){

     dosomething();
     sleep(2000);

 }

}

我的问题是,结束这 2 个线程的正确方法是什么?

谢谢!

【问题讨论】:

    标签: c++ multithreading winapi mfc


    【解决方案1】:

    一般来说,结束线程的正确方法是要求它完成,然后等待它完成。因此,在 Windows 上,您可能会发出一个事件来要求线程完成,然后等待线程 HANDLE。强行终止线程几乎总是一个错误的想法,它会再次困扰您。

    【讨论】:

    • 谢谢史蒂夫。删除 pMyThread 时发出线程结束信号是否聪明?我的意思是:在 CWork 析构函数中放置而不是 while(true) - while(flag) 并设置 flag = false?
    • 你可以这样做。使用 Event 的好处是线程调度程序就在您身边。例如,不是休眠,而是使用带有超时的 WaitForSingleObject。这样线程就可以在休眠时响应信号,不需要忙等待。
    • 史蒂夫,如果我创建一个这样的线程: AfxBeginThread(RUNTIME_CLASS(CMyClass)... 如何结束这个线程?这与我错误地给出示例的第一个问题相反AfxBeginThread 使用类作为参数,而不是本来应该使用的 proc。谢谢。
    • @dushkin:如果没有 Windows API 的深入知识,你永远无法精通 MFC。如果你不知道RUNTIME_CLASS 宏的作用,那你就完蛋了。您的直接问题的答案很简单:您终止线程的方式与任何其他线程相同。请阅读Prerequisites for learning MFC programming,你会很感激你这样做的。
    【解决方案2】:

    创建一个调用CreateEvent 的事件,该事件最初是无信号的。当您的应用程序终止时,发送此事件 (SetEvent) 并等待线程终止(线程句柄上的 WaitForSingleObject)。

    在您的线程函数HandleNextVTSConnectionCommandProc 中,将您的while(true) 循环替换为

    while(WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
    

    执行上述操作可让您向线程发出信号以终止您的应用程序。当线程从其线程 proc 返回时,线程终止。

    【讨论】:

      【解决方案3】:

      设置一个标志而不是使用 while(true) 来告诉您的线程何时应该结束。你也可以使用事件。

      您还应该在退出之前等待线程完成,因此您应该使用(在主代码中,一旦您发出线程结束信号):

      WaitForSingleObject(thread_handle)
      

      【讨论】:

        【解决方案4】:

        这样的事情应该可以帮助您入门:

        HANDLE g_hThreadExitRequest = NULL;
        
        UINT __cdecl ThreadFunction(LPVOID pParam)
        {
            AllocConsole();
            HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
        
            for (int i=1; true; ++i)
            {
                CStringA count;
                count.Format("%d\n", i);
                WriteFile(hCon, (LPCSTR)count, count.GetLength(), NULL, NULL);
        
                if (WaitForSingleObject(g_hThreadExitRequest, 1000) == WAIT_OBJECT_0)
                    break;
            }
        
            // We can do any thread specific cleanup here.
            FreeConsole();
        
            return 0;
        }
        
        void Go()
        {
            // Create the event we use the request the thread exit.
            g_hThreadExitRequest = CreateEvent(
                                        NULL,   // LPSECURITY_ATTRIBUTES lpEventAttributes
                                        TRUE,   // BOOL bManualReset
                                        FALSE,  // BOOL bInitialState
                                        NULL    // LPCTSTR lpName
                                        );
        
            // We create the thread suspended so we can mess with the returned CWinThread without
            // MFC auto deleting it when the thread finishes.
            CWinThread *pThread = AfxBeginThread(
                                        &ThreadFunction,        // AFX_THREADPROC pfnThreadProc
                                        NULL,                   // LPVOID pParam
                                        THREAD_PRIORITY_NORMAL, // int nPriority
                                        0,                      // UINT nStackSize
                                        CREATE_SUSPENDED ,      // DWORD dwCreateFlags
                                        NULL                    // LPSECURITY_ATTRIBUTES lpSecurityAttrs
                                        );
        
            // Turn off MFC's auto delete "feature".
            pThread->m_bAutoDelete = FALSE;
        
            // Start the thread running.
            pThread->ResumeThread();
        
            // Wait 30 seconds.
            Sleep(30*1000);
        
            // Signal the thread to exit and wait for it to do so.
            SetEvent(g_hThreadExitRequest);
            WaitForSingleObject(pThread->m_hThread, INFINITE);
        
            // Delete the CWinTread object since we turned off auto delete.
            delete pThread;
        
            // We're finished with the event.
            CloseHandle(g_hThreadExitRequest);
            g_hThreadExitRequest = NULL;
        }
        

        【讨论】:

        • 我的新问题是关于使用类作为 AfxBeginThread 的参数 - AfxBeginThread(RUNTIME_CLASS(CMyClass)...。关于将线程 proc 作为参数的 AfxBeginThread - 我成功地使用了你的建议。谢谢。
        猜你喜欢
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多