Multithreading: Vytváření pracovních podprocesů
Pracovní vlákno se běžně používá ke zpracování úkolů na pozadí, na které by neměl muset uživatel čekat pro pokračování v používání aplikace.Úlohy jako je přepočet a tisk na pozadí jsou dobrým příkladem pracovních vláken.Toto téma podrobně popisuje kroky, potřebné k vytvoření pracovního vlákna.Témata zahrnují:
Spuštění vlákna
Implementace řídící funkce
Příklad
Vytvoření pracovního vlákna je poměrně jednoduchá úloha.Pouze dva kroky jsou požadovány pro spuštění vašeho vlákna: implementace řídící funkce a spuštění vlákna.Není nutné odvozovat třídu z CWinThread.Můžete třídu odvodit, pokud potřebujete speciální verzi CWinThread, ale není to vyžadováno pro většinu jednoduchých pracovních vláken.Můžete použít CWinThread beze změny.
Spuštění vlákna
Existují dvě přetížené verze AfxBeginThread: jeden, který lze vytvořit pouze pracovních podprocesů a jeden, který můžete vytvářet vlákna uživatelského rozhraní a pracovních podprocesů.Chcete-li zahájit provádění vašeho pracovního vlákna pomocí první přetížení, zavolejte AfxBeginThread, poskytuje následující informace:
Adresa řídící funkce.
Parametr, který má být předán řídící funkci.
(nepovinné) Požadovaná priorita vlákna.Výchozí hodnota je normální priorita.Další informace o možných úrovních priority naleznete v tématu SetThreadPriority v Windows SDK.
(nepovinný) Požadovaná velikost zásobníku pro vlákno.Výchozí hodnota je stejná velikost zásobníku jako u vytvářeného vlákna.
(nepovinný) CREATE_SUSPENDED pokud chcete, aby bylo vlákno vytvořeno v pozastaveném stavu.Výchozí hodnota je 0 nebo normální spuštění vlákna.
(nepovinný) Požadované atributy zabezpečení.Výchozí hodnota je stejný přístup jako nadřazené vlákno.Další informace o formátu informací zabezpečení naleznete v tématu SECURITY_ATTRIBUTES v Windows SDK.
AfxBeginThread vytvoří a inicializuje objekt CWinThread spustí jej a vrátí jeho adresu, takže je možné se na něj později odkazovat.Kontroly jsou prováděny v celém procesu, aby bylo zajištěno, že všechny objekty jsou správně zrušeny, takže by neměla selhat žádná část tvorby.
Implementace řídící funkce
Řídící funkce definuje vlákno.Po zadání této funkce se vlákno spustí a při jejím ukončení se vlákno ukončí.Tato funkce by měla mít následující prototyp:
UINT MyControllingFunction( LPVOID pParam );
Parametr je jednoduchá hodnota.Hodnota, kterou funkce přijímá v tomto parametru je hodnota, která byla předána konstruktoru při vytvoření objektu vlákna.Řídící funkce může interpretovat tuto hodnotu jakýmkoli způsobem si vybere.Může být považována za skalární hodnotu nebo ukazatel na strukturu, obsahující více parametrů nebo může být ignorována.Pokud parametr odkazuje na strukturu, struktura může být použita nejen pro předání dat od volajícího vláknu, ale také k předání dat zpět z vlákna volajícímu.Použijete-li takovouto strukturu k předání dat zpět volajícímu, musí vlákno oznámit volajícímu kdy jsou výsledky připraveny.Chcete-li zobrazit informace o komunikaci z pracovního vlákna k volajícímu, viz Multithreading: tipy pro programování.
Když funkce skončí, měla by vrátit hodnotu UINT, označující důvod ukončení.Obvykle je tento kód ukončení 0 pro označení úspěchu nebo jiné hodnoty, označující různé typy chyb.Toto závisí čistě na implementaci.Některá vlákna mohou udržovat počty využití objektů a vracet aktuální počet využití daného objektu.Chcete-li zjistit, jak mohou aplikace načíst tuto hodnotu, viz Multithreading: ukončení vlákna.
Existují některá omezení na to, co můžete dělat ve vícevláknovém programu, vytvořeném pomocí knihovny MFC.Pro popisy těchto omezení a jiné tipy pro používání vláken, viz Multithreading: tipy pro programování.
Příklad řídící funkce
Následující příklad ukazuje, jak definovat řídící funkci a použít ji z jiné části programu.
UINT MyThreadProc( LPVOID pParam )
{
CMyObject* pObject = (CMyObject*)pParam;
if (pObject == NULL ||
!pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
return 1; // if pObject is not valid
// do something with 'pObject'
return 0; // thread completed successfully
}
// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.