21
Programowanie Programowanie wielowątkowe wielowątkowe Jarosław Kuchta Jarosław Kuchta

Programowanie wielowątkowe

Embed Size (px)

DESCRIPTION

Jarosław Kuchta. Programowanie wielowątkowe. Procesy i wątki w systemie Windows. Windows jest systemem wielowątkowym. Każdy proces ma przynajmniej jeden wątek, chociaż może mieć wiele wątków. Start programu, to start głównego wątku procesu. Główny wątek może uruchomić inny, poboczny wątek. - PowerPoint PPT Presentation

Citation preview

Programowanie Programowanie wielowątkowewielowątkowe

Jarosław KuchtaJarosław Kuchta

Procesy i wątki w Procesy i wątki w systemie Windowssystemie Windows

Windows jest systemem wielowątkowym.Windows jest systemem wielowątkowym. Każdy proces ma przynajmniej jeden Każdy proces ma przynajmniej jeden

wątek, chociaż może mieć wiele wątków.wątek, chociaż może mieć wiele wątków. Start programu, to start głównego wątku Start programu, to start głównego wątku

procesu.procesu. Główny wątek może uruchomić inny, Główny wątek może uruchomić inny,

poboczny wątek.poboczny wątek. Zamknięcie programu, to zamknięcie Zamknięcie programu, to zamknięcie

wszystkich wątków procesu.wszystkich wątków procesu.

Programowanie Programowanie wielowątkowe w języku Cwielowątkowe w języku C

Start programu:Start programu: main(), wmain() – w programie konsolimain(), wmain() – w programie konsoli WinMain(), wWinMain() – w programie WinMain(), wWinMain() – w programie

okienkowymokienkowym Procedura osobnego wątku:Procedura osobnego wątku:

void ThreadProc(void *param)void ThreadProc(void *param)

{{

……

_endthread();_endthread(); // zakończenie wątku // zakończenie wątku

}}

Funkcje sterujące Funkcje sterujące wątkamiwątkami

zadeklarowane w process.h:zadeklarowane w process.h: _beginthread_beginthread – rozpoczęcie wątku – rozpoczęcie wątku _beginthreadex_beginthreadex – rozszerzone rozpoczęcie – rozszerzone rozpoczęcie

wątkuwątku _endthread_endthread – zakończenie wątku – zakończenie wątku _endthreadex_endthreadex – rozszerzone zakończenie – rozszerzone zakończenie

wątkuwątku

Przykład – funkcja Przykład – funkcja wątkuwątku

void ThreadProc(void *param)void ThreadProc(void *param)

{{

// ten wątek po prostu wypisuje parametr// ten wątek po prostu wypisuje parametr

int h=*((int*)param);int h=*((int*)param);

printf("%d Thread is Running!\n",h);printf("%d Thread is Running!\n",h);

_endthread();_endthread();

}}

Przykład – funkcja Przykład – funkcja głównagłówna

int main()int main(){{

int n;int n; int i;int i; int val = 0;int val = 0; HANDLE handle;HANDLE handle; printf("\t Thread Demo\n");printf("\t Thread Demo\n"); printf("Enter the number of threads : ");printf("Enter the number of threads : "); scanf("%d",&n);scanf("%d",&n); for(i=1;i<=n;i++)for(i=1;i<=n;i++) {{

val = i;val = i; handle = (HANDLE) handle = (HANDLE)

_beginthread( ThreadProc,0,&val); // _beginthread( ThreadProc,0,&val); // utworzenieutworzenie wątkuwątku WaitForSingleObject(handle,INFINITE);WaitForSingleObject(handle,INFINITE); // oczekiwanie // oczekiwanie

na zakończenie wątkuna zakończenie wątku }} return 0;return 0;

}}

Programowanie Programowanie wielowątkowe w MFCwielowątkowe w MFC

Hierarchia klas MFC:Hierarchia klas MFC: CObjectCObject – obiekt abstrakcyjny – obiekt abstrakcyjny CCmdTargetCCmdTarget – obiekt aktywny – obiekt aktywny CWinThreadCWinThread – wątek Windows – wątek Windows CWinAppCWinApp – aplikacja Windows – aplikacja Windows

Aplikacja Windows jest wątkiem!Aplikacja Windows jest wątkiem! Dwa rodzaje wątków:Dwa rodzaje wątków:

User Interface – wątek oparty o oknaUser Interface – wątek oparty o okna Worker – wątek pracujący w tleWorker – wątek pracujący w tle

Użyteczne daneUżyteczne dane

m_nThreadIDm_nThreadID – identyfikator bieżącego – identyfikator bieżącego wątkuwątku

m_hThread m_hThread – uchwyt bieżącego wątku– uchwyt bieżącego wątku m_bAutoDelete m_bAutoDelete – czy wątek ma się sam – czy wątek ma się sam

usunąć po zamknięciu?usunąć po zamknięciu?

Funkcje wątkoweFunkcje wątkowe Funkcje globalne:Funkcje globalne:

AfxBeginThreadAfxBeginThread – utworzenie wątku – utworzenie wątku AfxEndThreadAfxEndThread – zamknięcie wątku – zamknięcie wątku

Metody obiektowe:Metody obiektowe: CreateThreaCreateThread – utworzenie i wystartowanie d – utworzenie i wystartowanie

wątkuwątku SuspendThreadSuspendThread – zawieszenie wątku – zawieszenie wątku

(inkrementacja licznika zawieszeń)(inkrementacja licznika zawieszeń) ResumeThreadResumeThread – wznowienie wątku – wznowienie wątku

(dekrementacja licznika zawieszeń)(dekrementacja licznika zawieszeń) SetThreadPrioritySetThreadPriority – ustawienie priorytetu wątku – ustawienie priorytetu wątku GetThreadPriorityGetThreadPriority – pobranie priorytetu wątku – pobranie priorytetu wątku

Priorytety wątkówPriorytety wątków

THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_IDLETHREAD_PRIORITY_IDLE

Przykład z użyciem Przykład z użyciem funkcji Afxfunkcji Afx

CwinThread *pThread = AfxBeginThread( ThreadFunction, &data);CwinThread *pThread = AfxBeginThread( ThreadFunction, &data);

UINT ThreadFunction(LPVOID param)UINT ThreadFunction(LPVOID param)

{{

DWORD result =0 ;DWORD result =0 ;

// do somthig// do somthig

AfxEndThread(exitCode);AfxEndThread(exitCode);

return result;return result;

}}

Kończenie wątkuKończenie wątku

funkcja funkcja TerminateThreadTerminateThread()() funkcjafunkcja ExitThread ExitThread()() instrukcjainstrukcja return return – zalecana, pozostałe – zalecana, pozostałe

nie czyszczą stosu.nie czyszczą stosu.

Programowanie Programowanie wielowątkowe w C# (1)wielowątkowe w C# (1)

// współdzielona zmienna// współdzielona zmienna private string _threadOutput = ""; private string _threadOutput = "";

// funkcja pierwszego wątku// funkcja pierwszego wątku void DisplayThread1()void DisplayThread1(){{

while (_stopThreads == false)while (_stopThreads == false){{

Console.WriteLine("Display Thread 1");Console.WriteLine("Display Thread 1");_threadOutput = "Hello Thread1";_threadOutput = "Hello Thread1";Thread.Sleep(1000); // symulacja działania pierwszego Thread.Sleep(1000); // symulacja działania pierwszego

wątkuwątku

Console.WriteLine("Thread 1 Output --> {0}", Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);_threadOutput); } }

}}

Programowanie Programowanie wielowątkowe w C# (2)wielowątkowe w C# (2)

// funkcja drugiego wątku// funkcja drugiego wątku void DisplayThread2()void DisplayThread2(){{

while (_stopThreads == false)while (_stopThreads == false){{

Console.WriteLine("Display Thread 2");Console.WriteLine("Display Thread 2");_threadOutput = "Hello Thread2";_threadOutput = "Hello Thread2";Thread.Sleep(1000); // symulacja działania drugiego Thread.Sleep(1000); // symulacja działania drugiego

wątkuwątku

Console.WriteLine("Thread 2 Output --> {0}", Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);_threadOutput);}}

}}

Programowanie Programowanie wielowątkowe w C# - wielowątkowe w C# -

inicjacja wątkówinicjacja wątkówClass1()Class1(){{ // utworzenie dwóch wątków// utworzenie dwóch wątków

Thread thread1 = new Thread(new Thread thread1 = new Thread(new ThreadStart(DisplayThread1));ThreadStart(DisplayThread1));

Thread thread2 = new Thread(new Thread thread2 = new Thread(new ThreadStart(DisplayThread2));ThreadStart(DisplayThread2));

// wystartowanie wątków// wystartowanie wątkówthread1.Start();thread1.Start();

thread2.Start();thread2.Start();} }

WynikWynik

Współdzielona zmienna jest asynchronicznie nadpisywana

Synchronizacja przez Synchronizacja przez lock (1)lock (1)

// współdzielona zmienna// współdzielona zmienna private string _threadOutput = ""; private string _threadOutput = "";

// funkcja pierwszego wątku// funkcja pierwszego wątku void DisplayThread1()void DisplayThread1(){{

while (_stopThreads == false) while (_stopThreads == false) { {

lock (this) // blokada na własnej instancji lock (this) // blokada na własnej instancji {{

Console.WriteLine("Display Thread 1");Console.WriteLine("Display Thread 1"); _threadOutput = "Hello Thread1";_threadOutput = "Hello Thread1"; Thread.Sleep(1000); // symulacja działania pierwszego Thread.Sleep(1000); // symulacja działania pierwszego

wątkuwątku

Console.WriteLine("Thread 1 Output --> {0}", Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);_threadOutput);

}}}}

}}

Synchronizacja przez Synchronizacja przez lock (2)lock (2)

// funkcja drugiego wątku// funkcja drugiego wątkuvoid DisplayThread2()void DisplayThread2(){{

while (_stopThreads == false)while (_stopThreads == false){{

lock(this) // blokada na własnej instancjilock(this) // blokada na własnej instancji{{

Console.WriteLine("Display Thread 2"); Console.WriteLine("Display Thread 2"); _threadOutput = "Hello Thread2"; _threadOutput = "Hello Thread2";

Thread.Sleep(1000); // symulacja działania Thread.Sleep(1000); // symulacja działania drugiego wątkudrugiego wątku

Console.WriteLine("Thread 2 Output --> {0}", Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);_threadOutput);

}} } }

}}

Wynik (po Wynik (po synchronizacji)synchronizacji)

Synchronizacja przez Synchronizacja przez AutoResetEvent (1)AutoResetEvent (1)

// zmienne sygnałowe do wzajemnego odblokowywania// zmienne sygnałowe do wzajemnego odblokowywaniaAutoResetEvent _blockThread1 = new AutoResetEvent(false);AutoResetEvent _blockThread1 = new AutoResetEvent(false);AutoResetEvent _blockThread2 = new AutoResetEvent(true);AutoResetEvent _blockThread2 = new AutoResetEvent(true);

void DisplayThread_1()void DisplayThread_1(){{

while (_stopThreads == false)while (_stopThreads == false){{

// pierwszy wątek czeka, gdy drugi działa// pierwszy wątek czeka, gdy drugi działa_blockThread1.WaitOne(); _blockThread1.WaitOne(); // po wołaniu Set przez drugi wątek, pierwszy kontynuuje // po wołaniu Set przez drugi wątek, pierwszy kontynuuje

działaniedziałanie Console.WriteLine("Display Thread 1");Console.WriteLine("Display Thread 1");_threadOutput = "Hello Thread 1";_threadOutput = "Hello Thread 1";Thread.Sleep(1000); // symulacja działania pierwszego wątkuThread.Sleep(1000); // symulacja działania pierwszego wątku

Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);Console.WriteLine("Thread 1 Output --> {0}", _threadOutput); // zakończenie działania – odblokowanie drugiego wątku // zakończenie działania – odblokowanie drugiego wątku _blockThread2.Set(); _blockThread2.Set();

}}}}

Synchronizacja przez Synchronizacja przez AutoResetEvent (2)AutoResetEvent (2)

void DisplayThread_2()void DisplayThread_2() {{

while (_stopThreads == false)while (_stopThreads == false){{

// drugi wątek czeka, gdy pierwszy działa// drugi wątek czeka, gdy pierwszy działa_blockThread2.WaitOne(); _blockThread2.WaitOne(); // po wołaniu Set przez pierwszy wątek, drugi kontynuuje // po wołaniu Set przez pierwszy wątek, drugi kontynuuje

działaniedziałanieConsole.WriteLine("Display Thread 2");Console.WriteLine("Display Thread 2");_threadOutput = "Hello Thread 2";_threadOutput = "Hello Thread 2";Thread.Sleep(1000); // symulacja działania drugiego wątkuThread.Sleep(1000); // symulacja działania drugiego wątku

Console.WriteLine("Thread 2 Output --> {0}", Console.WriteLine("Thread 2 Output --> {0}", _threadOutput); _threadOutput); 

// zakończenie działania – odblokowanie pierwszego wątku // zakończenie działania – odblokowanie pierwszego wątku _blockThread1.Set();_blockThread1.Set();

}}}}