W poprzednim artykule opisałem podstawowe zagadnienia z dziedziny wielowątkowości, a także wyjaśniłem zasadę działania wątków typu Worker.
Zapoznanie się z poprzednim artykułem jest fakultatywne ;D:
http://blog.kacki.pl/dev/worker-threads/.
Wstęp
Cała platforma bada opiera się o wielowątkowość typu Event-driven threads (opartej na zdarzeniach), gdzie aby zakończyć wątek, trzeba wysłać sygnał końca metodą Stop().
Dodatkowo wątki tego typu umożliwiają wysyłanie i odbieranie komunikatów do/z innych wątków (asynchroniczne operacje).
Tworzenie
Aby stworzyć wątek typu Event-Driven wystarczy wyprowadzić nową klasę dziedziczącą po klasie Thread. Dla przypomnienia hierarchia klas:
Klasa Thread posiada kilka metod wirtualnych, których implementacja jest opcjonalna.
Oto niektóre z nich:
virtual bool OnStart(void); virtual void OnStop(void); virtual Osp::Base::Object* Run(void);
OnStart() – Zdarzenie uruchomienia wątku.
OnStop() – Zdarzenie zatrzymania wątku.
Klasa Thread dostarcza domyślną implementację metody Run() z interfejsu IRunnable – nie powinniśmy jej przesłaniać – jeśli to zrobimy, wątek będzie się zachowywał jak typu Worker i po wyjściu z tej metody wątek zostanie automatycznie zakończony.
Implementacja
/*
* MyTask.h
*
* Created on: 28-10-2011
* Author: markac
*/
#ifndef MYTASK_H_
#define MYTASK_H_
#include <FBase.h>
using namespace Osp::Base;
using namespace Osp::Base::Runtime;
class MyTask :
public Thread
{
public:
MyTask();
virtual ~MyTask();
virtual bool OnStart(void);
virtual void OnStop(void);
};
#endif /* MYTASK_H_ */
/*
* MyTask.cpp
*
* Created on: 28-10-2011
* Author: markac
*/
#include "MyTask.h"
MyTask::MyTask() {
// TODO Auto-generated constructor stub
}
MyTask::~MyTask() {
// TODO Auto-generated destructor stub
}
bool MyTask::OnStart()
{
// inicjalizacja zadania i uruchomienie
return true; // false - natychmiastowe zakończenie wątku
}
void MyTask::OnStop()
{
// zwolnij zajęte zasoby
}
Uruchamianie
MyTask* pThread = new MyTask(); pThread->Construct(THREAD_TYPE_EVENT_DRIVEN); // THREAD_TYPE_WORKER dla typu Worker pThread->Start();
Zatrzymywanie
Aby zakończyć wątek, wywołujemy metodę Stop().
// zatrzymaj zadanie pThread->Stop(); // tylko dla typu THREAD_TYPE_EVENT_DRIVEN // czekaj na zakończenie zadania pThread->Join(); // usuń wątek delete pThread; pThread = null;
Różnice między wątkami typu Worker i Event-Driven
Dobrze ilustruje to poniższy obrazek, który zdecydowałem się przytoczyć jeszcze raz.
Worker threads – po wykonaniu zadania w ciele metody Run(), wątek zostaje automatycznie zakończony.
Event-driven threads – wątek z obsługą zdarzeń/powiadomień, działający do chwili uzyskania sygnału zatrzymania metodą Stop().
Na tym różnice się nie kończą. Wątki typu Event-Driven posiadają obsługę zdarzeń/sygnałów odbieranych z innych wątków.
O komunikacji między wątkami będzie traktował jeden z kolejnych artykułów.
Podsumowanie
Aby stworzyć wątek typu Worker:
- Wyprowadzamy nową klasę implementującą interfejs IRunnable lub dziedziczącą po klasie Thread.
- Przesłaniamy metodę Run() i w ciele metody umieszczamy nasze zadanie.
- Zakończenie wątku nastąpi automatycznie po wyjściu z metody Run().
Aby stworzyć wątek typu Event-Driven:
- Wyprowadzamy nowa klasę dziedziczącą po klasie Thread.
- Nie przesłaniamy domyślnej metody Run(), a zadanie umieszczamy w metodzie OnStart().
- Kończymy wątek metodą Stop().


Dyskusja dostępna także na forum:
http://forum.badadev.pl/viewtopic.php?id=52