Многопотоковые программы

Принципно новым свойством Windows, отличающим ее от других операционных систем, является возможность написания многопотоковых программ. Это свойство позволяет программеру более много и тонко управлять ходом выполнения как программки в целом, так и отдельных ее частей. Это дает возможность создавать более действенные программки. К примеру, в одном потоке можно решать задачку Многопотоковые программы сорти­ровки данных, в другом – сбора инфы от удаленных источников, а в 3-ем – задачку обработки инфы, вводимой юзером. Ввиду способности потоковой многозадачности в Windows эти потоки производятся сразу, конкурируя вместе за процессорное время, потому центральный микропроцессор не простаивает.

Принципиально осознать, что все процессы имеют как минимум один поток Многопотоковые программы выполнения. Для удобства изложения он будет называться основным потоком. Но можно сделать более чем один поток выполнения в одном процессе. Вновь сделанный поток сразу начинает производиться наряду с основным. Таким макаром, каждый процесс начинает производиться в одном (главном) потоке и по ходу выполнения может создавать один либо более дополнительных Многопотоковые программы потоков. Это и есть метод написания многопотоковых программ в Windows.


В этом разделе мы разглядим, как разрабатываются многопотоковые программки.

Создание потока. Для сотворения потока употребляется функция API CreateThread(). Вот макет этой функции:

HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpAttr,

DWORDdwStack,

LPTHREAD_START_ROUTINE lpFunc,

LPVOID lpParam, DWORD dwFlags,

LPDWORD lpdwID);

Тут параметр lpAttr является Многопотоковые программы указателем на структуру атрибутов доступа, предо­ставляемых создаваемому процессу. В Windows XP (также NT либо 2000), этот указатель может быть равен NULL.

Каждый поток имеет собственный свой стек. Размер стека для создаваемого потока в б можно найти в параметре dwStack. Если же значение этого параметра равно 0, стек создаваемого потока имеет Многопотоковые программы таковой же размер, как и стек родительского потока; по мере надобности он будет расширяться. Потому в большинстве случаев в качестве значения этого параметра задают 0.

Выполнение каждого потока начинается с вызова функции, именуемой потоко­вой функцией, и длится до окончания этой функции. Адресок потоковой функции (точки входа для потока Многопотоковые программы) задается в параметре lpFunc. Все потоковые функции обязаны иметь последующий макет:

DWORD threadfunc(LPVOID param);

Хоть какой аргумент, который Вы желаете задать для нового потока, определяется при разработке потока в параметре lpParam функции CreateThread(). Это 32-разрядное значение передается в качестве параметра в потоковую функцию и может быть применено для всех Многопотоковые программы целей.

Параметр dwFlags определяет состояние потока. Если его значение равно 0, выпол­нение потока начинается немедля. Если это значение равно CREATE_SUSPEND, то поток будет находиться в состоянии ожидания до поступления сигнала, разрешающего начало выполнения. (Разрешить выполнение потока в данном случае можно с помощью функции ResumeThread().) Идентификатор сделанного потока записывается Многопотоковые программы в двойное слово, адресок которого передается в параметре lpdwID.

Функция возвращает дескриптор сделанного потока при успешном окончании или нуль при появлении ошибки.

Окончание потока. Как уже было сказано, поток заканчивается при возвращении из потоковой функции. Не считая того, родительский процесс может принудительно окончить его с помощью вызова функции TerminateThread():

BOOL TerminateThread Многопотоковые программы(HANDLE hThread, DWORD dwStatus);

Параметр hThread содержит дескриптор потока, который должен быть завершен, a dwStatus определяет код окончания. Функция возвращает ненулевое значение при успешном окончании и нуль при появлении ошибки.

Поток, завершаемый с помощью вызова функции TerminateThread(), прекра­щает выполнение немедля и не делает никаких действий Многопотоковые программы по освобождению памяти, ресурсов и т.п. Не считая того, функция TerminateThread() может окончить поток, выполняющий в это время какую-нибудь важную операцию. Потому обычно наилучшим (и простым) методом окончания потока является окончание потоко­вой функции. Конкретно этот подход употребляется в примерах данной главы.

Пример 12-2. Многопотоковая программка

Приведенная ниже программка делает новый Многопотоковые программы поток всякий раз при поступлении команды меню Новый поток.Этот поток 10 раз подает звуковой сигнал и при всем этом выводит на экран его номер совместно с идентификатором потока. Другой поток может быть сотворен до того, как закончится поток, сделанный по предшествующей команде.

Звуковой сигнал генерируется при вызове функции API Beep Многопотоковые программы(). Эта функция имеет последующий вид:

BOOL Beep(DWORD frequency, DWORD duration);

Параметр frequency – это высота (тональность) звука в герцах, а duration – длительность звучания в миллисекундах. К примеру, если необходимо получить сигнал с тональностью звука 600 герц и длительностью 0,25 секунды, необходимо выполнить функцию

Beep(600, 250); // 600 Гц, 0,25 сек

В качестве базы для этой программки Многопотоковые программы употребляется текст, рассмотренный в примере 12-1. Также применяется техно­логия виртуального окна для отображения и обновления содержимого реального окна.

// Обычная многопотоковая программка,

// с внедрением виртуального окна

#include

#include

#include

#include "Proc.h"

#define Procmax 5

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

DWORD MyThread(LPVOID); // Функция потока

char szWinName[] = "МоеОкно"; // Имя класса Многопотоковые программы окна

char str[255]; // Буфер строчки вывода

int X=0, Y=0; // Текущие координаты строчки

int procnum=0; // Количество активных процессов

DWORD Tid; // Идентификатор потока

int maxX, maxY; // Размеры экрана

HDC memdc; // DC виртуального окна

HBITMAP hbit; // Растр - это виртуальное окно

HBRUSH hbrush; // Дескриптор кисти

PROCESS_INFORMATION pinfo[Procmax];

int WINAPI WinMain (HINSTANCE hThisInst,

HINSTANCE hPrevInst,

LPSTR lpszArgs,

int nWinMode)

{

HWND hwnd;

MSG msg Многопотоковые программы;

WNDCLASS wcl;

HACCEL hAccel;

// Найти класс окна

wcl.hInstance=hThisInst; // Дескриптор приложения

wcl.lpszClassName=szWinName; // Имя класса окна

wcl.lpfnWndProc=WindowFunc; // Функция окна

wcl.style=0; // Стиль по дефлоту

wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка

wcl.hCursor=LoadCursor(NULL,IDC_ARROW) ; // Курсор

wcl.lpszMenuName="MYMENU"; // Меню

wcl.cbClsExtra=0; // Без дополнительной

wcl.cbWndExtra=0; // инфы

// Найти наполнение окна белоснежным цветом

wcl.hbrBackground Многопотоковые программы=

(HBRUSH)GetStockObject(WHITE_BRUSH);

if(!RegisterClass(&wcl)) // Зарегистр. класс окна

return 0;

// Сделать окно

hwnd=CreateWindow(szWinName, // Имя класса

"Порождение процессов и потоков",

WS_OVERLAPPEDWINDOW,// Стиль окна

CW_USEDEFAULT, // Х-координата

CW_USEDEFAULT, // Y-координата

CW_USEDEFAULT, // Ширина окна

CW_USEDEFAULT, // Высота окна

HWND_DESKTOP, // Нет родит. окна

NULL, // Нет меню

hThisInst, // Дескрип. приложения

NULL); // Без дополит. аргументов

// Загрузить акселераторы

hAccel Многопотоковые программы=LoadAccelerators(hThisInst,"MYMENU");

ShowWindow(hwnd,nWinMode) ; // Показать окно и

UpdateWindow(hwnd); // перерисовать содержимое

// Запустить цикл обработки сообщений

while(GetMessage (&msg,NULL,0,0))

if(!TranslateAccelerator(hwnd,hAccel,&msg))

{

TranslateMessage(&msg); // Использ.Клавиатуры

DispatchMessage (&msg); // Возврат к Windows

}

return msg. wParam;

}

// Последующая функция вызывается операционной системой

// Windows и получает в качестве характеристик сообщения

// из очереди сообщений данного приложения

LRESULT CALLBACK WindowFunc Многопотоковые программы(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT paintstruct;

TEXTMETRIC tm;

STARTUPINFO startin;

switch(message)

{

case WM_CREATE: // Получаем размеры экрана

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

hdc=GetDC(hwnd); // Совмест. с окном растр

memdc=CreateCompatibleDC(hdc);

hbit=CreateCompatibleBitmap(hdc,maxX,maxY);

SelectObject(memdc,hbit Многопотоковые программы);

hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);

SelectObject(memdc,hbrush);

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

ReleaseDC(hwnd,hdc);

break;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_PROCESS:

if(procnum == Procmax)

{

MessageBox(hwnd,

"Нельзя сделать больше",

"Ошибка", MB_OK);

break;

} // Менее чем Procmax

// Получить метрики текста */

GetTextMetrics(memdc, &tm);

sprintf(str, "Порождается процесс %d Многопотоковые программы",

procnum);

TextOut(memdc, X, Y, str, strlen(str));

Y = Y+tm.tmHeight+tm.tmExternalLeading;

InvalidateRect(hwnd,NULL,1); //Сказать

// Порождение нового процесса

startin.cb=sizeof(STARTUPINFO);

startin.lpReserved = NULL;

startin.lpDesktop = NULL;

startin.lpTitle = NULL;

startin.dwFlags =STARTF_USESHOWWINDOW;

startin.cbReserved2 = 0;

startin.lpReserved2 = NULL;

startin.wShowWindow = SW_SHOWMINIMIZED;

CreateProcess(NULL, "Test Многопотоковые программы.exe", NULL,

NULL, FALSE, 0, NULL,

NULL, &startin,

&(pinfo[procnum]));

procnum++;

break;

case ID_KILLPROC:

if(procnum)

procnum--;

else

{

MessageBox(hwnd,

"Больше процессов нет",

"Ошибка", MB_OK);

break;

}

// Получить метрики текста

GetTextMetrics(memdc, &tm);

TerminateProcess

(pinfo[procnum].hProcess, 0);

sprintf(str, "Процесс %d завершен",

procnum);

TextOut(memdc, X, Y, str, strlen(str Многопотоковые программы));

Y = Y+tm.tmHeight+tm.tmExternalLeading;

InvalidateRect(hwnd,NULL,1); //Сказать

break;

case ID_THREAD:

CreateThread

(NULL, 0,

(LPTHREAD_START_ROUTINE)MyThread,

(LPVOID)NULL, 0, &Tid);

InvalidateRect (hwnd, NULL, 1);

break;

case ID_HELP:

MessageBox(hwnd,

"F2: Новый процесс\n"

"F3: Окончить процесс\n"

"F4: Новый поток",

"Помощь:", MB_OK);

InvalidateRect(hwnd,NULL,1); //Сказать

break;

}

break;

case WM_PAINT Многопотоковые программы: // Перерисовка окна

hdc=BeginPaint(hwnd,&paintstruct); // Пол. DC

// Сейчас копируем растр из памяти на экран

BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

EndPaint(hwnd,&paintstruct); // Высвободить DC

break;

case WM_DESTROY: // Окончание программки

DeleteDC(memdc); // Удалить виртуальное окно

PostQuitMessage(0);

break;

default:

// Все сообщения, не обрабатываемые в данной

// функции, направляются на обработку по

// умолчанию

return DefWindowProc(hwnd,message,

wParam Многопотоковые программы,lParam);

}

return 0;

}

//

// Начало выполнения нового потока

//

DWORD MyThread(LPVOID param)

{

int i;

DWORD curTid = Tid;

TEXTMETRIC tm;

// Получить метрики текста

GetTextMetrics(memdc, &tm);

for(i=0; i<10; i++)

{

Sleep(500); // Задержка 0,5 сек

sprintf(str, "Поток %ld, сигнал %d", curTid, i);

TextOut(memdc, X, Y, str, strlen(str));

Y = Y + tm.tmHeight + tm.tmExternalLeading Многопотоковые программы;

InvalidateRect((HWND)param, NULL, 1) ;

Beep(600, 250); // 600 Гц, 0,25 сек

}

return 0;

}

Результаты работы этой многопотоковой программки приведены на рисунке 12.2.

Рис. 12.2. Пример окна многопотоковой программки


Для работы программки будет нужно файл ресурсов Process.rc из предшествующего примера, который дополнен кнопкой меню Новый поток и подходящим акселератором:

#include

#include "Proc.h"

MYMENU MENU

{

POPUP "Процессы"

{

MENUITEM "Новый процесс Многопотоковые программы", ID_PROCESS

MENUITEM "Окончить процесс", ID_KILLPROC

MENUITEM "Новый поток", ID_THREAD

}

MENUITEM "Помощь", ID_HELP

}

MYMENU ACCELERATORS

{

VK_F2, ID_PROCESS, VIRTKEY

VK_F3, ID_KILLPROC, VIRTKEY

VK_F4, ID_THREAD, VIRTKEY

VK_F1, ID_HELP, VIRTKEY

}

Соответственно, употребляется тот же файл Proc.h, дополненный новейшей константой:

#define ID_PROCESS 100

#define ID_KILLPROC 101

#define ID_THREAD 102

#define ID Многопотоковые программы_HELP 103


mnogofunkcionalnie-reagenti.html
mnogofunkcionalnij-energosberegayushij-imitacionnij-nagruzochnij-kompleks-dlya-sistem-elektropitaniya-kosmicheskih-apparatov.html
mnogofunkcionalnost-uprazhneniya-i-mnogofaktornost-umeniya-referat.html