Multithreading: Erstellen von Arbeitsthreads
Aktualisiert: November 2007
Ein Arbeitsthread wird normalerweise zur Behandlung von Hintergrundaufgaben verwendet. Auf diese Weise muss der Benutzer nicht auf deren Beendung warten, um mit der Anwendung weiterarbeiten zu können. Aufgaben wie Neuberechnung und Hintergrunddruck sind gute Beispiele für Arbeitsthreads. In diesem Thema werden die notwendigen Schritte zur Erstellung eines Arbeitsthreads ausführlich erläutert. Folgende Themen werden behandelt:
Starten des Threads
Implementieren der Steuerungsfunktion
Beispiel
Die Erstellung eines Arbeitsthreads ist eine verhältnismäßig einfache Aufgabe. Zur Aktivierung des Threads sind lediglich zwei Schritte erforderlich: das Implementieren einer Steuerungsfunktion und das Starten des Threads. Das Ableiten einer Klasse von CWinThread ist nicht erforderlich. Sie können eine Klasse ableiten, wenn Sie eine spezielle Version von CWinThread benötigen, dies ist jedoch für die meisten einfachen Arbeitsthreads nicht erforderlich. CWinThread kann unverändert verwendet werden.
Starten des Threads
Es gibt zwei überladene Versionen von AfxBeginThread: eine für Benutzeroberflächenthreads und eine für Arbeitsthreads. Rufen Sie AfxBeginThread auf, um die Ausführung des Arbeitsthreads zu starten, und geben Sie folgende Informationen an:
Die Adresse der Steuerungsfunktion
Den an die Steuerungsfunktion zu übergebenden Parameter
(Optional) Die gewünschte Priorität des Threads Standardmäßig ist normale Priorität eingestellt. Weitere Informationen zu den verfügbaren Prioritätsebenen finden Sie im Windows SDK unter SetThreadPriority.
(Optional) Die gewünschte Stapelgröße für den Thread. Standardmäßig wird die Größe des Erstellungsthreads verwendet.
(Optional) CREATE_SUSPENDED, wenn der Thread im unterbrochenen Zustand generiert werden soll Standardmäßig ist 0 eingestellt; Sie können den Thread auch normal starten.
(Optional) Die gewünschten Sicherheitsattribute Standardmäßig werden dieselben Zugriffsrechte wie für den übergeordneten Thread verwendet. Weitere Informationen zum Format dieser Sicherheitsinformationen finden Sie im Windows SDK unter SECURITY_ATTRIBUTES.
AfxBeginThread generiert und initialisiert ein CWinThread-Objekt automatisch, startet es und gibt seine Adresse zurück, damit Sie zu einem späteren Zeitpunkt darauf Bezug nehmen können. Während der gesamten Prozedur wird überprüft, ob alle Objekte ordnungsgemäß freigegeben werden, falls ein Teil des Erstellungsprozesses fehlschlagen sollte.
Implementieren der Steuerungsfunktion
Der Thread wird durch die Steuerungsfunktion definiert. Der Thread beginnt am Anfang dieser Funktion und wird bei Erreichen des Endes dieser Funktion terminiert. Diese Funktion sollte folgenden Prototyp aufweisen:
UINT MyControllingFunction( LPVOID pParam );
Bei dem Parameter handelt es sich um einen einzelnen Wert. Der Wert, den die Funktion in diesem Parameter empfängt, ist der Wert, der bei der Erstellung des Threadobjekts an den Konstruktor übergeben wurde. Die Steuerungsfunktion kann diesen Wert auf beliebige Art und Weise interpretieren: Er kann als Skalarwert oder als Zeiger auf eine Struktur mit mehreren Parametern behandelt werden, oder er kann ignoriert werden. Falls sich der Parameter auf eine Struktur bezieht, kann diese nicht nur zur Übergabe von Daten vom Aufrufer an den Thread verwendet werden, sondern auch zur Rückgabe von Daten vom Thread an den Aufrufer. Wenn Sie eine Struktur dieser Art zur Rückgabe von Daten an den Aufrufer verwenden, muss der Aufrufer vom Thread benachrichtigt werden, sobald die Ergebnisse verfügbar sind. Informationen zur Kommunikation zwischen Arbeitsthread und Aufrufer finden Sie unter Multithreading: Tipps für die Programmierung.
Bei Beendung der Funktion sollte ein UINT-Wert zurückgegeben werden, aus dem der Grund für die Beendung hervorgeht. Normalerweise lautet dieser Exitcode 0; dies steht für eine erfolgreiche Ausführung. Andere Werte stehen für unterschiedliche Fehlertypen. Dies hängt ausschließlich von der Implementierung ab. Einige Threads verwalten eventuell einen Verwendungszähler für Objekte und geben die aktuelle Anzahl der Verwendungen des jeweiligen Objekts zurück. Weitere Informationen dazu, wie dieser Wert von Anwendungen abgerufen werden kann, finden Sie unter Multithreading: Beenden von Threads.
Multithreadprogramme, die mit der MFC-Bibliothek geschrieben wurden, haben einige Einschränkungen. Eine Beschreibung dieser Einschränkungen sowie weitere Tipps zur Verwendung von Threads finden Sie unter Multithreading: Tipps für die Programmierung.
Beispiel einer Steuerungsfunktion
Aus dem folgenden Beispiel geht hervor, wie Sie eine Steuerungsfunktion definieren und diese von einem anderen Teil des Programms aus verwenden.
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);
.
.
.