Обновленный класс TEventThread

В позапрошлом посте я подробно описал класс TEventThread, реализующий управление потоком с помощью функции PulseEvent. Пришло время немного доработать этот класс.

Ниже приводится объявление класса TEventThread.

#ifndef TEventThreadH
#define TEventThreadH
#include <Classes.hpp>
//--------------------------------------------------------------------
class TEventThread : protected TThread
{
private:
   //Описатель объекта событие
   HANDLE hEvent;

   //Признак того, что работа выполнена
   bool WorkDone;
   //Признак необходимости остановки
   bool NeedStop;

   //Полностью завершает работу потока
   void StopThread();

protected:

   bool GetNeedStop() const {return this->NeedStop;};
   //Функция потока
   void __fastcall Execute();

   virtual void Work(){};

public:
   __fastcall TEventThread();
   __fastcall virtual ~TEventThread();

   bool IsWorkDone() const {return this->WorkDone;};

   //Пробуждает поток
   void Pulse() const {PulseEvent(this->hEvent);};
   //Останавливает расчет
   void StopCalc();

};
#endif

Рассмотрим основные изменения.

  • Появился виртуальный метод Work(). Он не имеет входных параметров и ничего не возвращает. Данный метод должен перегружаться потомками класса. Именно в нем реализуется вся основная работа потока.

  • Появился метод GetNeedStop, возвращающий значение флага NeedStop. Он нужен для того, чтобы потомки нашего класса могли определять значение флага NeedStop, но при этом не могли изменять его.

Теперь посмотрим, какой стала функция потока.

void __fastcall TEventThread :: Execute()
{
   while(true)
   {
      //Ждем когда нас разбудят
      WaitForSingleObject(this->hEvent, INFINITE);
      if(this->GetNeedStop()) break;
      this->WorkDone = false;
      //Выполняем работу
      this->Work();
      //Работа выполнена
      this->WorkDone = true;
   }
}

Обратите внимание: здесь остался только один, внешний цикл. Внутренний цикл заменен вызовом метода Work.

Класс TEventThread не выполняет никакой работы. Единственная его задача – это реализация управления рабочим потоком. Рабочий поток является потомком класса TEventThread и выполняет какую-то реальную работу. Он должен перегрузить метод Work(). В данном методе и выполняется вся работа. Рабочий поток ни в коем случае не должен перегружать метод Execute(). Это приведет к поломке всей системы управления.

Ниже приводится объявление класса TThreadCounter, реализующего поток со счетчиком на базе класса TEventThread.

#ifndef TThreadCounterH
#define TThreadCounterH
#include "TEventThread.h"
//--------------------------------------------------------------------
class TThreadCounter : public TEventThread
{
private:
   //Счетчик
   unsigned long Count;

protected:
   void Work();

public:
   TThreadCounter(): Count(0) {};

   unsigned long GetCount() const {return this->Count;};

};
#endif

Ниже приводится реализация метода Work() в классе TThreadCounter.h

void TThreadCounter :: Work()
{
   while(true)
   {
      if(this->GetNeedStop()) break;
      ++(this->Count);
      Sleep(1000);
   }
}

Он полностью включает в себя внутренний цикл.

По ссылке ниже вы можете скачать полный исходный текст примера со счетчиком. Данный пример аналогичен примеру, приводимому в позапрошлом посте, с той лишь разницей, что построен он на базе обновленного класса TEventThread.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *