Multithreading: Ukončování vláken v prostředí MFC
Dvě normální situace způsobí ukončení vlákna: řídicí funkce se ukončí nebo vlákno není povoleno spouštět do dokončení. Pokud textový procesor použil vlákno pro tisk na pozadí, řídicí funkce by se normálně ukončila, pokud se tisk úspěšně dokončil. Pokud ale uživatel chce tisk zrušit, musí být vlákno pro tisk na pozadí ukončeno předčasně. Toto téma vysvětluje, jak implementovat každou situaci a jak získat ukončovací kód vlákna po ukončení.
Normální ukončení vlákna
Pro pracovní vlákno je normální ukončení vlákna jednoduché: Ukončete řídicí funkci a vraťte hodnotu, která označuje důvod ukončení. Můžete použít funkci AfxEndThread nebo return
příkaz. Obvykle 0 označuje úspěšné dokončení, ale to je na vás.
Pro vlákno uživatelského rozhraní je proces stejně jednoduchý: z vlákna uživatelského rozhraní volejte PostQuitMessage v sadě Windows SDK. Jediný parametr, který PostQuitMessage
přebírá, je ukončovací kód vlákna. Pokud jde o pracovní vlákna, 0 obvykle označuje úspěšné dokončení.
Předčasné ukončení vlákna
Ukončení vlákna je téměř stejně jednoduché: Volání AfxEndThread z vlákna. Jako jediný parametr předejte požadovaný ukončovací kód. Tím se zastaví spuštění vlákna, uvolní se zásobník vlákna, odpojte všechny knihovny DLL připojené k vláknu a odstraníte objekt vlákna z paměti.
AfxEndThread
musí být volána z vlákna, která má být ukončena. Pokud chcete ukončit vlákno z jiného vlákna, musíte nastavit komunikační metodu mezi dvěma vlákny.
Načtení ukončovacího kódu vlákna
Chcete-li získat ukončovací kód pracovního procesu nebo vlákna uživatelského rozhraní, zavolejte funkci GetExitCodeThread . Informace o této funkci naleznete v sadě Windows SDK. Tato funkce přebírá popisovač do vlákna (uloženého v datovém m_hThread
členu CWinThread
objektů) a adresu DWORD.
Pokud je vlákno stále aktivní, GetExitCodeThread
umístí STILL_ACTIVE na zadanou adresu DWORD. Jinak se do této adresy umístí ukončovací kód.
Načtení ukončovacího kódu objektů CWinThread provede další krok. Ve výchozím nastavení, když vlákno CWinThread
ukončí, objekt vlákna je odstraněn. To znamená, že nemůžete získat přístup k datovému členu m_hThread
CWinThread
, protože objekt již neexistuje. Pokud se chcete této situaci vyhnout, udělejte jednu z těchto věcí:
m_bAutoDelete
Nastavte datový člen na FALSE. To umožňujeCWinThread
objektu přežít po ukončení vlákna. Po ukončení vlákna pak můžete získat přístup k datovémum_hThread
členu. Pokud však použijete tuto techniku, zodpovídáte za zničení objektuCWinThread
, protože architektura ho automaticky neodstraní za vás. Toto je upřednostňovaná metoda.Uložte rukojeť vlákna samostatně. Po vytvoření vlákna zkopírujte jeho
m_hThread
datový člen (pomocí::DuplicateHandle
) do jiné proměnné a přejděte k němu prostřednictvím této proměnné. Tímto způsobem se objekt automaticky odstraní, když dojde k ukončení, a stále můžete zjistit, proč vlákno skončilo. Před duplikátem popisovače buďte opatrní, že se vlákno neukončí. Nejbezpečnější způsob, jak to udělat, je předat CREATE_SUSPENDED AfxBeginThread, uložit popisovač a potom pokračovat ve vlákně voláním ResumeThread.
Obě metody umožňují určit, proč CWinThread
se objekt ukončil.
Viz také
Multithreading s použitím jazyka C++ a prostředí MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread