一种不会导致资源泄露的“终止”线程的方法
? ? ? ? 在項目工程中,我們可能會使用第三方開發的模塊。該模塊提供一個接口用于完成非常復雜和耗時的工作。我們一般不會將該API放在UI線程中執行,而是啟動一個線程,用工作線程去執行這個耗時的操作。(轉載請指明出于breaksoftware的csdn博客)
static VOID OtherPartFun() // 第三方提供函數,超級耗時,不如來個極限,死循環
{int nIndex = 0;while ( true ) {nIndex++;printf("%d\n",nIndex);Sleep( ONESECOND );}
}
// 我們啟動的線程函數,用于在工作線程中執行那個耗時的第三方提供函數
static DWORD WINAPI ThreadRoutine(LPVOID lpParam)
{OtherPartFun();return 0;
}
? ? ? ? 以上方法很好解決了不堵塞關鍵線程的目的。但是問題永遠不會間斷。比如當我們在某些條件下,我們要終止該線程的執行。如何做呢?
? ? ? ? 一是讓該模塊設計方提供一個終止線程接口,比如給我們一個事件,我們通過設置這個事件來通知該線程退出。
static VOID OtherPartFun()
{int nIndex = 0;while ( WAIT_OBJECT_0 != WaitForSingleObject( g_ExitEvent, 1000) ) {nIndex++;printf("%d\n",nIndex);Sleep( ONESECOND );}
}
? ? ? ? 另一種可能就是TerminateThread。
? ? ? ? 如果方案1對方不提供, 你也無法接受方案二導致的資源未釋放。那有如何辦呢?
? ? ? ? 目前有個方案是使用SEH。我們刻意造成該線程產生異常,同時在函數中捕獲該異常,以使得線程可以體面的退出。
? ? ? ? 以下我詳細講解下這個方案。
? ? ? ? 1 線程函數加上SEH捕獲異常。這樣我們認為制造異常后,不會導致進程出問題。
static DWORD WINAPI ThreadRoutine(LPVOID lpParam)
{__try {OtherPartFun(); // 第三方的耗時函數,我們用__try包住它。}__except(EXCEPTION_EXECUTE_HANDLER) {printf("Except!Thread will exit.\n"); // 我們認為觸發異常后會進入該邏輯。}return 0;
}
? ? ? ? 2 設置異常。我們設置異常的大體思路是
? ? ? ? A 掛起線程
? ? ? ? ?B 獲取線程EIP
? ? ? ? ?C 修改線程EIP為違例地址
? ? ? ? ?D 恢復線程
? ? ? ? ?我們看下代碼
HANDLE hThread = NULL;hThread = CreateThread( NULL, 0, ThreadRoutine, NULL, 0, NULL ); // 創建線程Sleep( 2 * ONESECOND ); // 模擬做點事情SuspendThread(hThread); // 掛起線程CONTEXT ThreadContext;ThreadContext.ContextFlags = CONTEXT_CONTROL; // 設置要獲取EIP寄存器GetThreadContext( hThread, &ThreadContext ); // 獲取EIP寄存器 ThreadContext.Eip = NULL; // 將EIP寄存器改成違例地址,這樣在恢復線程執行后,線程會適時拋出異常SetThreadContext(hThread , &ThreadContext); // 保存EIPResumeThread(hThread); // 恢復線程,線程即將退出Sleep( 15 * ONESECOND );if ( NULL != hThread ) {CloseHandle(hThread);hThread = NULL;}
? ? ? ? 我們看下執行結果
? ? ? ? 可以發現,我們線程“體面”的退出了。
? ? ? ? 其實這個方案也是存在不完善的地方的。比如我們線程產生了死鎖等,線程將進入內核態等待。這個時候我們獲取的EIP是客戶態函數的著陸點。而我們此時去修改EIP,還是要等待線程從內核態返回后才能觸發異常。
? ? ? ? 提供下該例子的工程
總結
以上是生活随笔為你收集整理的一种不会导致资源泄露的“终止”线程的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DllMain中不当操作导致死锁问题的分
- 下一篇: 在windows程序中嵌入Lua脚本引擎