Работа с несколькими потоками




 

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

· более высокий звук 600 Гц с задержкой между звуками 0,5 сек;

· звук низкой тональности 300 Гц с задержкой между звуками 0,2 сек.

Продолжительность обоих звуков 0,25 сек.

 


Пример 12-3. Программа с двумя порожденными потоками

 

// Многопотоковая программа с двумя потоками,

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

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Proc.h"

#define Procmax 5

 

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

DWORD MyThread1(LPVOID); // Функция 1-го потока

DWORD MyThread2(LPVOID); // Функция 2-го потока

char szWinName[] = "МоеОкно"; // Имя класса окна

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

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

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

DWORD Tid1; // Идентификатор 1-го потока

DWORD Tid2; // Идентификатор 3-го потока

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)MyThread1,

(LPVOID)NULL, 0, &Tid1);

CreateThread

(NULL, 0,

(LPTHREAD_START_ROUTINE)MyThread2,

(LPVOID)NULL, 0, &Tid2);

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;

}

 

//

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

//

 

DWORD MyThread1(LPVOID param)

{

int i;

DWORD curTid = Tid1;

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;

}

 

//

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

//

 

DWORD MyThread2(LPVOID param)

{

int i;

DWORD curTid = Tid2;

TEXTMETRIC tm;

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

GetTextMetrics(memdc, &tm);

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

{

Sleep(200); // Задержка 0,20 сек

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(300, 250); // 300 Гц, 0,25 сек

}

return 0;

}

 

 

Рис. 12.3. Окно программы с индикацией двух потоков

 

Пример окна этой программы представлен на рис. 12.3. Из текста этой программы следует, что при создании нескольких потоков для каждого из них необходимо определить потоковую функцию и использовать отдель­ный вызов функции CreateThread(). Все потоки одного процесса выполняются параллельно. Это видно из последовательности вывода информационных строк в главном окне программы.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: