03.Programowanie wielowatkowe

Download Report

Transcript 03.Programowanie wielowatkowe

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.
Zamknięcie programu, to zamknięcie wszystkich
wątków procesu.
Programowanie wielowątkowe w
języku C

Start programu:



main(), wmain() – w programie konsoli
WinMain(), wWinMain() – w programie okienkowym
Procedura osobnego wątku:
void ThreadProc(void *param)
{
…
_endthread(); // zakończenie wątku
}
Funkcje sterujące wątkami
zadeklarowane w process.h:
 _beginthread – rozpoczęcie wątku
 _beginthreadex – rozszerzone rozpoczęcie wątku
 _endthread – zakończenie wątku
 _endthreadex – rozszerzone zakończenie wątku
Przykład – funkcja wątku
void ThreadProc(void *param)
{
// ten wątek po prostu wypisuje parametr
int h=*((int*)param);
printf("%d Thread is Running!\n",h);
_endthread();
}
Przykład – funkcja główna
int main()
{
int n;
int i;
int val = 0;
HANDLE handle;
printf("\t Thread Demo\n");
printf("Enter the number of threads : ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
val = i;
handle = (HANDLE) _beginthread( ThreadProc,0,&val); // utworzenie wątku
WaitForSingleObject(handle,INFINITE); // oczekiwanie na zakończenie
wątku
}
return 0;
}
Programowanie wielowątkowe w
MFC

Hierarchia klas MFC:






CObject – obiekt abstrakcyjny
CCmdTarget – obiekt aktywny
CWinThread – wątek Windows
CWinApp – aplikacja Windows
Aplikacja Windows jest wątkiem!
Dwa rodzaje wątków:


User Interface – wątek oparty o okna
Worker – wątek pracujący w tle
Użyteczne dane



m_nThreadID – identyfikator bieżącego wątku
m_hThread – uchwyt bieżącego wątku
m_bAutoDelete – czy wątek ma się sam usunąć po
zamknięciu?
Funkcje wątkowe

Funkcje globalne:



AfxBeginThread – utworzenie wątku
AfxEndThread – zamknięcie wątku
Metody obiektowe:





CreateThread – utworzenie i wystartowanie wątku
SuspendThread – zawieszenie wątku (inkrementacja licznika
zawieszeń)
ResumeThread – wznowienie wątku (dekrementacja licznika
zawieszeń)
SetThreadPriority – ustawienie priorytetu wątku
GetThreadPriority – pobranie priorytetu wątku
Priorytety wątków





THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_IDLE
Przykład z użyciem funkcji Afx
CwinThread *pThread = AfxBeginThread( ThreadFunction, &data);
UINT ThreadFunction(LPVOID param)
{
DWORD result =0 ;
// do somthig
AfxEndThread(exitCode);
return result;
}
Kończenie wątku



funkcja TerminateThread()
funkcja ExitThread()
instrukcja return – zalecana, pozostałe nie czyszczą
stosu.
Programowanie wielowątkowe w
C# (1)
// współdzielona zmienna
private string _threadOutput = "";
// funkcja pierwszego wątku
void DisplayThread1()
{
while (_stopThreads == false)
{
Console.WriteLine("Display Thread 1");
_threadOutput = "Hello Thread1";
Thread.Sleep(1000); // symulacja działania pierwszego wątku
}
}
Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);
Programowanie wielowątkowe w
C# (2)
// funkcja drugiego wątku
void DisplayThread2()
{
while (_stopThreads == false)
{
Console.WriteLine("Display Thread 2");
_threadOutput = "Hello Thread2";
Thread.Sleep(1000); // symulacja działania drugiego wątku
Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);
}
}
Programowanie wielowątkowe w
C# - inicjacja wątków
Class1()
{
// utworzenie dwóch wątków
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// wystartowanie wątków
thread1.Start();
thread2.Start();
}
Wynik
Współdzielona zmienna jest asynchronicznie nadpisywana
Synchronizacja przez lock (1)
// współdzielona zmienna
private string _threadOutput = "";
// funkcja pierwszego wątku
void DisplayThread1()
{
while (_stopThreads == false)
{
lock (this) // blokada na własnej instancji
{
Console.WriteLine("Display Thread 1");
_threadOutput = "Hello Thread1";
Thread.Sleep(1000); // symulacja działania pierwszego wątku
Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);
}
}
}
Synchronizacja przez lock (2)
// funkcja drugiego wątku
void DisplayThread2()
{
while (_stopThreads == false)
{
lock(this) // blokada na własnej instancji
{
Console.WriteLine("Display Thread 2");
_threadOutput = "Hello Thread2";
Thread.Sleep(1000); // symulacja działania drugiego wątku
Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);
}
}
}
Wynik (po synchronizacji)
Synchronizacja przez
AutoResetEvent (1)
// zmienne sygnałowe do wzajemnego odblokowywania
AutoResetEvent _blockThread1 = new AutoResetEvent(false);
AutoResetEvent _blockThread2 = new AutoResetEvent(true);
void DisplayThread_1()
{
while (_stopThreads == false)
{
// pierwszy wątek czeka, gdy drugi działa
_blockThread1.WaitOne();
// po wołaniu Set przez drugi wątek, pierwszy kontynuuje działanie
Console.WriteLine("Display Thread 1");
_threadOutput = "Hello Thread 1";
Thread.Sleep(1000); // symulacja działania pierwszego wątku
Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);
// zakończenie działania – odblokowanie drugiego wątku
_blockThread2.Set();
}
}
Synchronizacja przez
AutoResetEvent (2)
void DisplayThread_2()
{
while (_stopThreads == false)
{
// drugi wątek czeka, gdy pierwszy działa
_blockThread2.WaitOne();
// po wołaniu Set przez pierwszy wątek, drugi kontynuuje działanie
Console.WriteLine("Display Thread 2");
_threadOutput = "Hello Thread 2";
Thread.Sleep(1000); // symulacja działania drugiego wątku
Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);
// zakończenie działania – odblokowanie pierwszego wątku
_blockThread1.Set();
}
}