Multithreading: Ukončení vláken
Dvě běžné situace způsobí ukončení vlákna: existuje řídící funkce nebo vláknu není povoleno dokončení.Pokud textový procesor používá vlákno pro tisk na pozadí, řídící funkce by jej měla ukončit normálně, jestliže je tisk úspěšně dokončen.Pokud chce však uživatel zrušit tisk, vlákno tisku na pozadí musí být předčasně ukončeno.Toto téma vysvětluje, jak implementovat obě situace a jak získat ukončovací kód vlákna poté, co je ukončeno.
Normální ukončení vlákna
Předčasné ukončení vlákna
Získání ukončovacího kódu vlákna
Normální ukončení vlákna
U pracovního vlákna je normální ukončení vlákna jednoduché: Ukončí řídící funkci a vrátí hodnotu, která označuje důvod ukončení.Můžete použít buď funkci AfxEndThread nebo příkaz return.Obvykle 0 znamená úspěšné dokončení, ale je to na vás.
Pro vlákno uživatelského rozhraní je proces stejně tak jednoduchý: prostřednictvím vlákna uživatelského rozhraní volejte PostQuitMessage v Windows SDK.Jediným parametrem, který PostQuitMessage přijímá, je ukončovací kód vlákna.Stejně jako u pracovních vláken 0 obvykle znamená úspěšné dokončení.
Předčasné ukončení vlákna
Předčasné ukončení vlákna je téměř stejně jednoduché: stačí z vlákna volat AfxEndThread.Předejte požadovaný ukončovací kód jako jediný parametr.To zastaví provádění vlákna, zruší přidělení zásobníku vlákna, odpojí všechny k vláknu připojené knihovny DLL a odstraní objekt vlákna z paměti.
Pro ukončení musí být AfxEndThread volána prostřednictvím vlákna.Pokud chcete ukončit vlákno z jiného vlákna, musíte nastavit metodu komunikace mezi těmito dvěma vlákny.
Získání ukončovacího kódu vlákna
Chcete-li získat ukončovací kód pracovního vlákna nebo vlákna uživatelského rozhraní, zavolejte funkci GetExitCodeThread.Informace o této funkci naleznete v tématu Windows SDK.Tato funkce přijímá zpracovávané vlákno (uložené v datovém členu m_hThread objektů CWinThread) a adresu DWORD.
Pokud je vlákno stále aktivní, GetExitCodeThread umístí STILL_ACTIVE do zadané adresy DWORD; v opačném případě zde umístí ukončovací kód.
Získání ukončovacího kódu objektů CWinThread vyžaduje ještě jeden krok navíc.Ve výchozím nastavení je při ukončení vlákna CWinThread objekt vlákna odstraněn.To znamená, že nebudete mít přístup k datovému členu m_hThread, protože objekt CWinThread již neexistuje.Aby k této situaci nedošlo, proveďte jeden z následujících pokynů:
Nastavte datový člen m_bAutoDelete na hodnotu FALSE.To umožňuje, aby byl objekt CWinThread zachován poté, co je vlákno ukončeno.Poté, co bylo vlákno ukončeno, můžete nadále přistupovat k datovému členu m_hThread.Pokud však použijete tento postup, zodpovídáte za zrušení objektu CWinThread, protože architektura jej neodstraní automaticky.Tohle je upřednostňovaná metoda.
Uložte popisovač vlákna zvlášť.Potom, co je vlákno vytvořeno, zkopírujte jeho datový člen m_hThread (pomocí ::DuplicateHandle) do jiné proměnné a přistupujte k němu prostřednictvím dané proměnné.Tímto způsobem bude objekt automaticky odstraněn, pokud dojde k ukončení, a můžete stále zjistit, proč bylo vlákno ukončeno.Dbejte na to, aby vlákno neskončilo dříve, než duplikujete popisovač.Nejbezpečnější způsob, jak to provést, je předat CREATE_SUSPENDED do AfxBeginThread, uložit popisovač a poté obnovit vlákno voláním ResumeThread.
Obě metody umožňují určit, proč byl ukončen objekt CWinThread.