Multithreading: Erstellen von Arbeitsthreads in MFC

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. Dabei werden folgende Themen behandelt:

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. Es ist nicht notwendig, eine Klasse von CWinThread abzuleiten. 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, mit der nur Arbeitsthreads erstellt werden können, und eine, mit der Benutzeroberflächenthreads und Arbeitsthreads erstellt werden können. Rufen Sie AfxBeginThread auf, um mit der Ausführung des Arbeitsthreads mit der ersten Überladung zu beginnen, und geben Sie die folgenden 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ätsstufen finden Sie unter SetThreadPriority im Windows SDK.

  • (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 in einem angehaltenen Zustand erstellt werden soll. Standardmäßig ist null0null 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 unter SECURITY_ATTRIBUTES im Windows SDK.

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 zum Kommunizieren vom Workerthread an den Aufrufer finden Sie unter Multithreading: Programmieren Tipps.

Wenn die Funktion beendet wird, sollte ein UINT-Wert zurückgegeben werden, der den Grund für die Beendigung angibt. Normalerweise lautet dieser Exitcode null0null; 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. Informationen dazu, wie Anwendungen diesen Wert abrufen können, finden Sie unter Multithreading: Beenden von Threads.

Multithreadprogramme, die mit der MFC-Bibliothek geschrieben wurden, haben einige Einschränkungen. Beschreibungen dieser Einschränkungen und anderer Tipps zur Verwendung von Threads finden Sie unter Multithreading: Programmieren Tipps.

Steuerelementfunktion (Beispiel)

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);
.
.
.

Worüber möchten Sie mehr erfahren?

Siehe auch

Multithreading mit C++ und MFC