Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Установка приоритета потока

.doc
Скачиваний:
30
Добавлен:
02.05.2014
Размер:
144.38 Кб
Скачать

Установка приоритета потока

Не все потоки должны создаваться равноправными. Существует возможность ус­тановки уровня приоритетности потока, чтобы поток получал больше или меньше ре­сурсов процессора по сравнению с другими потоками. Функция, которая служит для установки приоритета потока, называется SetThreadPriority().

Действительное количество циклов процессора, которые получает поток, зависит и от его приоритета, и от класса приоритета процесса, к которому этот поток при­надлежит. Для определения класса приоритета процесса можно пользоваться функ­цией GetPriorityClass(), а установки класса приоритета — SetPriorityClass(). Все фун­кции, о которых упоминается в этом разделе, являются функциями Windows API.

Программа, представленная в листингах 5.14 и 5.15, является С++ВшЫег-верси-ей программы, написанной на Delphi Дэвидом Интерсаймоном (David Intersimone), сотрудником Borland. Эту программу можно найти в каталоге ThSorts в коде, пред­назначенном для этой главы. Данная программа использует две пустые формы, на­званные Sec Form и ThForm. (У этой программы есть историческое прошлое: она была написана в самолете, пассажиры которого летели на презентацию Windows 95 в Си­этле, а после этого была усовершенствована в самолете по пути на недавнюю конфе­ренцию Borland в Германии.)

Листинг S.14. Заголовок программы Дэвида Интерсаймона Dreaded Sorts, версия

для C++Builder

//

#ifndef MainH #define MainH

//_ __ — __„______.„__.___ „ _._

#include <Classes.hpp>

#include <Controls.hpp>

♦include <StdCtrls.hpp>

ttinclude <Forms.hpp>

#include <ComCtrls.hpp>

//

const int pixeloffset = 5; // смещение пикселей отвечает за рамку внутри окна

// количество пикселей между главной формой и окнами сортировки const int formgap =10;

const TColor formcolor = clBlack; // цвет фона окон сортировки const TColor pixelcolor = clwhite; // цвет сортируемых элементов данных //

class TForml : public TFonn

{

published: // IDE-managed Components

TButton *Buttonl;

TEdit *Editl;

TLabel *Label1;

TLabel *Label2;

TLabel *Label3;

TTrackBar *BubbleTrackBar;

TTrackBar *QuickTrackBar;

TLabel *Label4;

TLabel *Label5;

void fastcall ButtonlClick(TObject «Sender);

void fastcall FormDestroy(TObject *Sender);

void fastcall FormCreate(TObject *Sender);

private: // User declarations

HANDLE Tl;

HANDLE T2;

int ScreenWidth, ScreenHeight, SortWindowClientArea;

int FrameSize, CaptionSizem, SortWindowSize; public: // User declarations

int* a;

int* b;

int Numltems;

fastcall TForml(TComponent* Owner);

};

//

extern PACKAGE TForml *Forml;

// _

#endif

Листинг 5.15. Главный модуль программы Дэвида Интерсаймона Dreaded Sorts,

версия C++Builder

//

#include <vcl.h>

#pragma hdrstop

//

#include "Main.h"

#include "SecForm.h"

#include "ThForm.h"

//

#pragma package(smart_init) #pragma resource "*.dfm" TForml *Forml;

/ / „ щ m _„_ ш

fastcall TForml::TForml(TComponent* Owner)

: TForm(Owner), a(0), b(0) {

)

//

// Процедура пузырьковой сортировки — вызывается функцией BubbleThread void BubbleSortfint* ia, int items) {

HDC DC = GetDC(Form2->Handle); int t;

for (int i = items;i>0;i--) {

for (int j = 0;j<items;j++) if (iatj] < ia[j+l]) {

t = ia[j];

// Чтобы взять значение из массива, используйте индекс SetPixel(DC, ia[j+l]+pixeloffset, j+1+pixeloffset, formcolor); SetPixeKDC, iatj] +pixeloffset, j+pixeloffeet, formcolor); ia[j] = ia[j+l]; ia[j + l] = t;

SetPixeKDC, ia[ j+1]+pixelof fset, j+1+pixelof fset, pixelcolor) ; SetPixeKDC, ia[j]+pixeloff set, j+pixelof fset, pixelcolor); } ) ReleaseDC(Form2->Handle, DC);

}

// --

// Быстрая сортировка - вызывается функцией QuickThread

void Quicksort(int* ia, int iLo, int iHi)

{

int T;

int Lo = iLo;

int Hi = iHi;

int mid = ia[(Lo+Hi) / 2];

HDC DC; .■•■..

do { .,'■,.' ■ '■■ • ! ■ ,■ :

DC = GetDC(Form3->Handle); while (ia[Lo] < mid)

Lo++; while (ia[Hi] > mid)

Hi — ;

if (Lo <= Hi) {

T = ia[Lo];

SetPixelfDC, ia[Lo)+pixelof£set,Lo+pixeloffset, formcolor); SetPixel(DC, ia[Hi]+pixeloffset,Hi+pixeloffset, formcolor); ia[Lo] = ia[Hi]; ia[Hi] = T;

SetPixel(DC, ia[Lo]+pixeloffset,Lo+pixeloffset, pixelcolor); SetPixel(DC, ia[Hi]+pixeloffset,Hi+pixeloffaet, pixelcolor); Lo++; Hi--;

// sleep(5); }

} while (Lo <= Hi);

if (Hi > iLo) Quicksort(ia,iLo,Hi); if (Lo < iHi) Quicksort (ia,Lo, iHi); ReleaseDC(Form3->Handle, DC);

}

/ /_ , ч —— „_ _.„ _«._

// Функция потока для пузырьковой сортировки

DWORD CALLBACK BubbleThread(void* parms)

{

BubbleSort(Porml->a,Porml->NumItems-l);

return 0; } //

// Функция потока для быстрой сортировки DWORD CALLBACK QuickThread(void* parms) {

Quicksort(Forml->b,0,Forml->NumItems-l);

return 0;

} - -

//

void fastcall TForml::ButtonlClick(TObject «Sender)

{

DWORD ThreadID;

// Размещение формы пузырьковой сортировки на рабочем столе

delete Form2;

Form2 = new TForm2(this);

Form2->Top = Forml->Top+Forml->Height+formgap;

Form2->Left = (ScreenWidth-(SortWindowSize*2)) / 2;

// Размещение окна пузырьковой сортировки на левой половине экрана

Form2->Width = SortWindowSize;

Porm2->Keight = SortWindowSize;

Form2->Color = formcolor;

Form2->Caption = "Bubble Sort";

Form2->Show();

// Размещение формы быстрой сортировки на рабочем стопе

delete Form3;

Form3 • new TForm3(this);

Form3->Top = Forml->Top+Forml->Height+formgap;

Form3->Left = Form2->Left+Form2->Width; // Размещение окна быстрой

// сортировки на правой половине экрана

Form3->Width = SortWindowSize;

Form3->Height = SortWindowSize;

Form3->Color = formcolor;

Form3->Caption = "Quick Sort";

Form3->Show() ;

// Набор элементов для сортировки, равный

// ширина клиентской области — смещение границ

Numltems = Form2->ClientHeight — pixeloffset*2;

// Распределение массива для хранения сортируемых данных

delete[] a;

а ■ new int[Numlterns];

delete [] b;

b = new int[Numltems];

// Генерация случайных чисел для сортировки

randomize();

for (int i = O;i<NumItems;i++)

{

a[i] ■ random(Numltems);

b[i] = a[i];

Form2->Canvas->Pixels[a[i]+pixeloffset][i+pixeloffeet] « pixelcolor;

Form3->Canvas->Pixels[b[i]+pixeloffset][i+pixeloffeet] a pixelcolor;

}

// Запуск потока пузырьковой сортировки

Tl ■ CreateThread(O,O,BubbleThread,O,O,&ThreadID);

// Установка приоритета потока в соответствии с позицией track bar

SetThreadPrioritytTl, BubbleTrackBar->Poeition);

// Запуск потока быстрой сортировки

Т2 = CreateThread(0,O,QuickThread,0,O,&ThreadID);

// Установка приоритета потока в соответствии с позицией track bar

SetThreadPriority(Т2, QuickTrackBar->Posit ion);

// ПРИМЕЧАНИЕ: Для того чтобы осуществить быструю рекурсивную // сортировку, установите приоритет ее потока в -1 II -2.

// Чтобы увидеть, сможет ли пузырьковая сортировка осуществляться быстрее // чем быстрая, установите приоритет потока пузырьковой сортировки в +2, // а быстрой в -2

)

// .

void fastcall TForml::FormDestroy(TObject *Sender)

<

delete [] a;

delete[] b;

)

/уиии¥ _ -_ __..__ — ___ — _

void fastcall TForml::FormCreate(TObject *Sender)

{

// Получаем размер рабочего стола

ScreenWidth = GetSystemMetrics(SM_CXSCREEN);

ScreenHeight = GetSystemMetrics(SM_CYSCREEN);

// Перемещаем главную форму вверх и в центр рабочего стола

Forml->Top = 0;

Forml->Left = (ScreenWidth - Forml->Width) / 2;

// Определяем, сколько элементов может быть показано в этих двух окнах

SortWindowSize = ScreenHeight-Forml->Height;

if (SortWindowSize > (ScreenWidth / 2))

SortWindowSize = ScreenWidth / 2; }

Программа Treaded Sorts создает два потока. Один поток выполняет пузырьковую сортировку, а второй — быструю сортировку. Вы можете использовать компоненты trackbar для повышения приоритета пузырьковой сортировки, чтобы она получила боль­ше циклов процессора, при одновременном понижении приоритета быстрой сорти­ровки. В конечном итоге можно достичь состояния, когда пузырьковая сортировка будет выполняться примерно за один и тот же интервал времени что и быстрая, не­смотря на то, что пузырьковая сортировка — это более медленный алгоритм. Две до­полнительных формы в проекте служат для визуального отображения процесса сор­тировок (рис. 5.5).

Рис. 5.5. Программа Threaded Sorts и вспомогательные окна, иллюстрирующие разные методы сортировки.

В коде устанавливается приоритет потоков:

Т1 = CreateThread(O,O,BubbleThread,O,O,&ThreadID); SetThreadPriority(Tl, BubbleTrackBar~>Position); Т2 = CreateThread(O,O,QuickThread,nil,O,&ThreadID); SetThreadPriority(T2, QuickTrackBar->Position);

Каждому потоку с помощью функции SetThreadPriorityO назначается его приоритет. Ниже приводится объявление функции SetThreadPriorityO:

BOOL SetThreadPriority(

HANDLE hThread, // дескриптор потока

int nPriority // уровень приоритетности потока

);

Во второй параметр функции SetThreadPriorityO могут быть переданы следующие константы:

THREAD_PRIORITY_ LOWEST = THREAD_BASE_PRIORITY_MIN; THREAD_PRIORITY__BELOW_NORMAL = THREAD__PRIORITY_LOWEST + 1; THREAD_PRIORITY_NORMAL = 0 ;

THREAD__PRIORITY_HIGHEST = THREAD_.BASE_PRIORITY_MAX; THREAD_PRIORITY._ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST - 1; THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_L0WRT; THREAD_PRIORITY._IDLE = THREAD_BASE__PRIORITY_IDLE;

Для того чтобы придать смысл значениям, указанным выше, можно использовать следующий код:

// приоритет устанавливается в значение LowRealtime — 1 THREAD_BASE_PRIORITY_LOWRT = 15;

// максимальное увеличение базовой приоритетности потока THREAD_BASE_PRIORITY__MAX = 2;

// максимальное уменьшение базовой приоритетности потока THREAD_BASE_PRIORITY_MIN ■ -2; THREAD__BASE_PRIORITY_IDLE = -15; // значение, останавливающее поток

ПРИМЕЧАНИЕ НАУЧНОГО РЕДАКТОРА

Вышеперечисленные четыре константы именно таким образом определены в заголовочном файле WINNT.H

Связанные с этой темой функции Windows API, описание которых можно найти в интерактивной справке Win32, — SetPriorityClass() и GetPriorityClass().

Программа Treaded Sorts интересна для изучения. Если вас увлекла эта тема, вам следует потратить на нее какое-то время. Можно и просто откинуться на спинку кресла и получить удовольствие, наблюдая за ее работой.

Повторный обзор потоков в C++Builder

Вы уже убедились в том, что даже довольно сложные манипуляции с потоками могут осуществляться достаточно просто. Используя информацию о мощной технологии потоков, полученную из этой книги, вы сможете многое сделать в своих программах. Однако будьте внимательны и не злоупотребляйте потоками. Если вы слишком ув­лечетесь, то, возможно, столкнетесь с проблемами, связанными с усложненной струк­турой программы. Используйте вторичные потоки только тогда, когда они действи­тельно необходимы и когда вы ясно понимаете, как они вписываются в вашу программу. Избегайте создавать программы, которые окажутся запутанным клубком потоков. Ре­зультатом этого будет сумбурность кода и сложность его сопровождения.

В многопроцессорных системах различные потоки могут выполняться на различ­ных процессорах, что является чрезвычайно мощной концепцией. Только представьте себе, что один Pentium выполняет графический код, второй анализирует электрон­ную таблицу, а третий в это же время открывает SQL-запрос. В многозадачном мире программирования в C++Builder возможно запустить даже потоки одновременно на