Krzysztof Mossakowski
Materiały dla studentów
 

Wielowątkowość
(klasa CWinThread)

MFC
Spis treści

Wielowątkowość
klasa CWinThread
Informacje ogólne
Wątki interfejsu użytkownika
Wątki robocze
Synchronizacja
Hierarchia klas

  •  Informacje ogólne

    • Proces - wykonywana instancja (instance) aplikacji

    • Wątek - ścieżka wykonywania w procesie

      • w jednym procesie może być równocześnie uruchomionych wiele wątków

    • Z punktu widzenia API Windows wszystkie wątki są takie same, natomiast w MFC można wyróżnić dwa rodzaje wątków:

      • wątki interfejsu użytkownika

      • wątki robocze

    • Wszystkie wątki aplikacji MFC powinny wykorzystywać klasę CWinThread

[początek strony]

  •  Wątki interfejsu użytkownika

    • Zwykle są używane do obsługi możliwości, jakie ma użytkownik, odpowiadają na komunikaty i zdarzenia przez niego generowane

    • Aplikacja (obiekt klasy CWinApp) jest także wątkiem interfejsu użytkownika

    • Schemat wykorzystania wątków interfejsu użutkownika:

      • utworzyć klasę wątku (dziedziczącą z CWinThread)
        - musi być zadeklarowana i zaimplementowana z dynamicznym tworzeniem (makra DECLARE_DYNCREATE i IMPLEMENT_DYNCREATE)

      • nadpisać potrzebne funkcje wirtualne:
        - CWinThread::InitInstance - inicjalizacja przed uruchomieniem, musi być nadpisana
        - CWinThread::ExitInstance - ostatnia funkcja przed zakończeniem pracy wątku, zwykle nadpisywana
        - CWinThread::Run - funkcja kontrolna wątku, rzadko nadpisywana
        - CWinThread::OnIdle - wywoływana gdy wątkowi brakuje czynności do wykonania, rzadko nadpisywana
        - CWinThread::PreTranslateMessage - filtruje komunikaty przed wysłaniem ich do funkcji CWinThread::TranslateMessage i CWinThread::DispatchMessage, rzadko nadpisywana
        - CWinThread::ProcessWndProcException - obsługa niewyłapanych wyjątków, rzadko nadpisywana

      • przy pomocy funkcji AfxBeginThread (z parametrem określającym klasę wątku) utworzyć obiekt wątku i uruchomić go
        - funkcja ta zwraca wskaźnik do utworzonego wątku

      • aby zakończyć wątek wywołać PostQuitMessage z parametrem określającym kod wyścia wątku

      • pobrać kod wyjścia wątku można przy pomocy funkcji GetExitCodeThread z parametrem CWinThread::m_hThread
        - możliwe jest to tylko, jeśli flaga wątku CWinThread::m_bAutoDelete była ustawiona na FALSE, co zapobiega automatycznemu usunięciu wątku po zakończeniu jego pracy

[początek strony]

  •  Wątki robocze

    • Są to wątki wykorzystywane zwykle tylko do przeprowadzenia obliczeń, które nie potrzebują interfejsu użytkownika

    • Schemat wykorzystania wątków roboczych:

      • utworzyć funkcję wątku
        - o prototypie:
        UINT ControllingFunction( LPVOID pParam )
        - parametrem tej funkcji jest wartość argumentu przekazywanego do konstruktora podczas tworzenia wątku (może to być wartość lub wskaźnik do struktury)
        - wartością zwracaną przez funkcję powinien być kod wyjścia, zwykle 0 jako sukces

      • uruchomić wątek przy pomocy funkcji AfxBeginThread (z parametrem określającym funkcję wątku)

      • zakończyć pracę wątku można w jeden ze sposobów:
        - zakończyć wykonywanie funkcji wątku
        - wywołać z wątku funkcję AfxEndThread

[początek strony]

  •  Synchronizacja

    • W przypadku wymiany danych pomiędzy wątkami może być konieczna synchronizacja, aby zapobiec konfliktom podczas dostępu do danych

    • Klasy obiektów synchronizacji:

      • CSyncObject
        - wirtualna klasa bazowa wszystkich obiektów synchronizacji

      • CSemaphore
        - dostęp do ograniczonej (większej niż 1) liczby zasobów
        - konkurujące wątki mogą być z różnych procesów

      • CMutex
        - dostęp do jednego zasobu (tylko jeden z wątków może w jednej chwili korzystać z tego zasobu)
        - wątki mogą być z różnych procesów

      • CCriticalSection
        - jeden zasób
        - wątki muszą być z jednego procesu

      • CEvent
        - daje możliwość zawiadomienia wątku o czymś
        - stosowane, gdy wątek musi zaczekać na coś

    • Klasy obiektów synchronizacji dostępu:

      • CSingleLock - dla pojedynczego obiektu synchronizacji

      • CMultiLock - dla wielu obiektów synchronizacji

      • schemat wykorzystania:
        - utworzyć obiekt lub obiekty synchronizacji i przekazać do tworzonego obiektu synchronizacji dostępu
        - przy pomocy CSingleLock::Lock lub CMultiLock::Lock czekać na dostęp
        - po otrzymaniu dostępu wykonać pożądane czynności
        - oddać dostęp przy pomocy CSingleLock::Unlock lub CMultiLock::Unlock

[początek strony]

  •  Hierarchia klas

    CObject - informacja w trakcie wykonywania, dynamiczne tworzenie, serializacja
        CCmdTarget - obsługa komunikatów Windows
            CWinThread
        CSyncObject
            CCriticalSection
            CEvent
            CMutex
            CSemaphore
    CSingleLock
    CMultiLock

[początek strony]