windows 結束線程有三種方式
一、讓線程函數執行到 return
二、在線程函數內調用 ExitThread
三、調用 TerminateThread
其中前兩種方式比較類似,它們都是通過修改某個變量來達到改變子線程執行流程,從而實現退出的目的。這兩種方式是同步的,安全的,線程退出後會系統會清理堆棧。
第三種方式 TerminateThread 是異步的,它會創建一個新的線程去結束我們希望幹掉的線程,該函數立即返回,是異步的。如果程序希望線程真的結束,然後再往下走,那麼就需要在 TerminateThread 後面調用 WaitForSingleObject 函數,阻塞等待線程真的結束。
如果希望子線程安全地退出,並執行釋放資源代碼,使用方式一;
如果希望子線程直接退出,沒有需要釋放的資源,可以使用方式二;
第三種方式結束線程不安全,系統不會清理子線程的堆棧,不推薦使用。
這是我寫的一個測試程序:
下面附上三種結束方式的實現
方式一(推薦)
// ThreadOperatorGUI.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
BOOL flag = TRUE; // 控制子線程結束
DWORD WINAPI MyThread(LPVOID lpParam)
{
HWND hEdit = (HWND)lpParam;
TCHAR szBuffer[10];
GetWindowText(hEdit, szBuffer, 10);
for (int i = 0; i <= 10000; i++)
{
if (!flag) break;
_stprintf(szBuffer, TEXT("%d"), i);
SetWindowText(hEdit, szBuffer);
Sleep(200);
}
return 0;
}
BOOL CALLBACK MainDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hEdit;
static HANDLE hThread;
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg, 0);
return TRUE;
}
case WM_INITDIALOG:
{
hEdit = GetDlgItem(hDlg, IDC_EDIT);
SetWindowText(hEdit, "0");
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
hThread = CreateThread(0, 0, MyThread, hEdit, 0, 0);
return TRUE;
}
case IDC_BUTTON2:
{
SuspendThread(hThread);
return TRUE;
}
case IDC_BUTTON3:
{
ResumeThread(hThread);
return TRUE;
}
case IDC_BUTTON4:
{
flag = FALSE;
return TRUE;
}
}
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDialogProc);
return 0;
}
方式二
// ThreadOperatorGUI.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
BOOL flag = TRUE; // 控制子線程結束
DWORD WINAPI MyThread(LPVOID lpParam)
{
HWND hEdit = (HWND)lpParam;
TCHAR szBuffer[10];
GetWindowText(hEdit, szBuffer, 10);
for (int i = 0; i <= 10000; i++)
{
if (!flag) ExitThread(1);
_stprintf(szBuffer, TEXT("%d"), i);
SetWindowText(hEdit, szBuffer);
Sleep(200);
}
return 0;
}
BOOL CALLBACK MainDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hEdit;
static HANDLE hThread;
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg, 0);
return TRUE;
}
case WM_INITDIALOG:
{
hEdit = GetDlgItem(hDlg, IDC_EDIT);
SetWindowText(hEdit, "0");
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
hThread = CreateThread(0, 0, MyThread, hEdit, 0, 0);
return TRUE;
}
case IDC_BUTTON2:
{
SuspendThread(hThread);
return TRUE;
}
case IDC_BUTTON3:
{
ResumeThread(hThread);
return TRUE;
}
case IDC_BUTTON4:
{
flag = FALSE;
return TRUE;
}
}
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDialogProc);
return 0;
}
方式三(不推薦)
// ThreadOperatorGUI.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
DWORD WINAPI MyThread(LPVOID lpParam)
{
HWND hEdit = (HWND)lpParam;
TCHAR szBuffer[10];
GetWindowText(hEdit, szBuffer, 10);
for (int i = 0; i <= 10000; i++)
{
_stprintf(szBuffer, TEXT("%d"), i);
SetWindowText(hEdit, szBuffer);
Sleep(200);
}
return 0;
}
BOOL CALLBACK MainDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hEdit;
static HANDLE hThread;
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg, 0);
return TRUE;
}
case WM_INITDIALOG:
{
hEdit = GetDlgItem(hDlg, IDC_EDIT);
SetWindowText(hEdit, "0");
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
hThread = CreateThread(0, 0, MyThread, hEdit, 0, 0);
return TRUE;
}
case IDC_BUTTON2:
{
SuspendThread(hThread);
return TRUE;
}
case IDC_BUTTON3:
{
ResumeThread(hThread);
return TRUE;
}
case IDC_BUTTON4:
{
TerminateThread(hThread, 123); // 結束碼123,可自定義
WaitForSingleObject(hThread, INFINITE); // 阻塞,直到hThread結束
return TRUE;
}
}
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDialogProc);
return 0;
}