Programowanie
wielowątkowe
Komunikaty i zdarzenia
Wątki w WindowsAPI
Wątki w Turbo C++ klasa TThread
Wątki w Turbo C++ - klasa TThread
Przesyłanie komunikatów między wątkami
Zagadnienie synchronizacji wątków
Zagadnienie synchronizacji wątków
Komunikacja między procesami
Model aplikacji sterowanej
zdarzeniami
zdarzeniami
Procesy wymieniają informacje za
pomocą komunikatów
pomocą komunikatów
W odpowiedzi na nadejście komunikatu
może zostać uruchomiony fragment kodu
może zostać uruchomiony fragment kodu
(procedura obsługi zdarzenia)
Identyfikacja komunikatów
Za pomocą unikalnego numeru
Zakres od
Zakres do
Opis
0x0000
0x03FF
Komunikaty systemowe
Komunikaty dostępne dla programistów, przeznaczone
0x0400
0x7FFF
do użycia przez kontrolki okienkowe. Numer 0x0400
ma stała WM_USER
0x8000
0xBFFF
Komunikaty wewnętrzne aplikacji. Numer 0x8000 ma
stała WM_APP
0xC000
0xFFFF
Tekstowe komunikaty używane przez aplikacje
Powyżej 0xFFFF
Numery zarezerwowane dla przyszłych wersji
Poprzez zdefiniowane stałe
WinSight32
Program WinSight32
Składnik niektórych pakietów Delphi i C++Builder
Lista procesów i komunikatów
Funkcje API wysyłające komunikat
Funkcje API wysyłające komunikat
BOOL PostMessage(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam);
PostMessage(Application->Handle,WM_USER,0, 0);
LRESULT SendMessage(HWND hWnd, UINT Msg,
WPARAM wParam
LPARAM lParam);
WPARAM wParam, LPARAM lParam);
SendMessage(Form2->Handle, WM_SYSCOMMAND,
SC_MAXIMIZE, 0);
Metody przetwarzania w tle
Reakcja programu na działania użytkownika:
przetwarzanie przychodzących komunikatów
Problem: złożone procesy obliczeniowe
Metoda Application->ProcessMessages();
Zdarzenie Application->OnIdle();
Utworzenie wątku drugoplanowego
Funkcje API tworzące wątki
HANDLE CreateThread(
LPSECURITY ATTRIBUTES lpThreadAttributes,
_
p
,
SIZE_T dwStackSize,
LPTHREAD START ROUTINE lpStartAddress,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
);
HANDLE CreateRemoteThread( /*...*/ );
Klasa TThread
Klasa biblioteki VCL
Obudowuje wywołanie funkcji API
Obudowuje wywołanie funkcji API
Szereg metod i właściwości
usprawniających i przyspieszających
budowę aplikacji wielowątkowych
Dostępny kreator z poziomu menu:
FileÆNewÆOther... --Æ Thread Object
FileÆNewÆOther... Æ Thread Object
Aplikacja wielowątkowa
Zadanie: posortować dane dwoma
algorytmami:
algorytmami:
Bąbelkowym (ang. bubble sort)
Selekcyjnym (ang selection sort)
Selekcyjnym (ang. selection sort)
Wykorzystać klasę TThread i metody
obiektowe: dziedziczenie, polimorfizm
i klasy abstrakcyjne
Wynik należy prezentować na ekranie
w postaci graficznej
w postaci graficznej
Komunikacja wątku
j
ą
drugoplanowego z aplikacją
Przesyłanie komunikatów z wnętrza wątku
const int WM_KONIECWATKU = WM_USER+1;
void __fastcall TWatek::Execute(){
...
SendMessage(Form3->Handle, WM KONIECWATKU, ThreadID, 0);
g
_
}
void __fastcall KoniecWatku(TMessage & M){
(
)
if(M.Msg == WM_KONIECWATKU){
ShowMessage("Koniec, ID="+IntToStr(M.WParam));
}
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_KONIECWATKU, TMessage, KoniecWatku);
END MESSAGE MAP(TForm);
END_MESSAGE_MAP(TForm);
Synchronizacja wątku drugorzędnego
Synchronizacja wątku drugorzędnego
z głównym wątkiem aplikacji
Klasa TThread
metoda Synchronize()
metoda Synchronize()
Różne klasy VCL (np. TCanvas,
TC t
Wi S k t TG
hi Obj t)
TCustomWinSocket, TGraphicObject)
metoda void Lock()
metoda bool TryLock()
Synchronizacja wątków w
y
j
ą
ramach jednej aplikacji
Sekcja krytyczna (ang. Critical Section)
Zablokowanie dostępu dla innych wątków do
współdzielonego zasobu
Ut
i k ji
k t
j l
d fi i
i
Utworzenie sekcji krytycznej polega na zdefiniowaniu
zmiennej typu TRTLCriticalSection:
TRTLCriticalSection sekcja;
TRTLCriticalSection sekcja;
Obsługa sekcji krytycznych:
void InitializeCriticalSection(TRTLCriticalSection *s);
void DeleteCriticalSection(TRTLCriticalSection *s);
void EnterCriticalSection(TRTLCriticalSection *s);
BOOL TryEnterCriticalSection(TRTLCriticalSection *s);
BOOL TryEnterCriticalSection(TRTLCriticalSection s);
void LeaveCriticalSection(TRTLCriticalSection *s);
Synchronizacja wątków różnych
y
j
ą
y
aplikacji
Obiekt Mutex (ang. MUTually EXclusive)
Stan nies gnali o an (ang non signaled) M te jest
Stan niesygnalizowany (ang. non-signaled) – Mutex jest
w posiadaniu jakiegoś wątku
Stan sygnalizowany (ang. signaled) – Mutex jest wolny
Stan sygnalizowany (ang. signaled) Mutex jest wolny
Utworzenie obiektu Mutex:
HANDLE CreateMutex(
LPSECURITY ATTRIBUTES att
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES att,
BOOL init, LPCTSRT ident);
HANDLE
t k
C
t M t
(NULL
0
"
j
t k ")
HANDLE muteks = CreateMutex(NULL, 0, "moj_muteks");
Przejęcie Mutexa
Funkcja API
DWORD WaitForSingleObject(HANDLE uchwyt, DWORD msek);
uchwyt obiektu Mutex
maksymalny czas oczekiwania (stała INFINITE)
Funkcja zwraca:
0x0080 (WAIT_ABANDONED) – przejęcie obiektu
po zakończonym wątku
0x0000 (WAIT_OBJECT_0) – obiekt był wolny
i został przejęty przez wątek
i został przejęty przez wątek
0x0102 (WAIT_TIMEOUT) – upłynął czas
oczekiwania na zwolnienie obiektu
Synchronizacja wątków różnych
y
j
ą
y
aplikacji
Obiekt Semafor
Działa na takiej zasadzie jak Mutex
j
j
Pozwala na zliczanie odwołań
Utworzenie obiektu Semafora:
Utworzenie obiektu Semafora:
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES att,
LONG initCount, LONG maxCount, LPCTSRT ident);
HANDLE sem = CreateSemaphore(NULL,0,1,"moj_sem");
Zarządzanie:
Zarządzanie:
OpenSemaphore(), ReleaseSemaphore(),
CloseHandle()
CloseHandle()
WaitForSingleObject(),WaitForMultipleObjects()