Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АОПИ. Старое / АОПИ. Глава 2. Конспекты (02_04_19).rtf
Скачиваний:
65
Добавлен:
10.09.2019
Размер:
363.46 Кб
Скачать

Функция создания вторичного потока _beginthread

Заголовочный файл: <process.h>

uintptr_t _beginthread(

IN unsigned (__stdcall *start_address)(void *),

IN unsigned stack_size,

IN void* arglist,

);

Краткое описание.

Создает поток.

Подпрограмма, которая указывается на месте первого параметра, должна содержать в конце своей работы инструкцию _endthread(); (перед return 0;)

Параметры и описание:

(1) start_address определяет начальный адрес подпрограммы, которая начинает выполнение нового потока.

(2) stack_size определяет размер стека для нового потока. Можно указать значение 0 — операционная система использует размер стека основного потока.

(3) arglist определяет cписок аргументов для передачи в новый поток. Можно указать значение NULL.

Возвращаемое значение:

Если функция завершается успешно, возвращается дескриптор созданного потока.

Если функция завершается с ошибкой, возвращается 0.

Пример использования этой функции приведен в ответе на домашнее задание про критические секции (см. ниже).

Функция создания вторичного потока _beginthreadex

Заголовочный файл: <process.h>

uintptr_t _beginthreadex(

IN void* security,

IN unsigned stack_size,

IN unsigned (__stdcall *start_address)(void *),

IN void* arglist,

IN unsigned initflag,

OUT unsigned* thrdaddr

);

Краткое описание.

Создает поток.

Подпрограмма, которая указывается на месте третьего параметра, должна содержать в конце своей работы инструкцию _endthreadex(0); (т. е. перед return 0;), где 0 — код возврата потока.

Параметры и описание:

(1) security является указателем на структуру SECURITY_ATTRIBUTES, которая определяет, может ли возвращаемый дескриптор наследоваться дочерними процессами. Если security имеет значение NULL, дескриптор не может быть унаследован. Должно быть указано NULL для приложений Windows 95.

(2) stack_size определяет размер стека для нового потока. Можно указать значение 0 — операционная система использует размер стека основного потока.

(3) start_address определяет начальный адрес подпрограммы, которая начинает выполнение нового потока.

(4) arglist определяет cписок аргументов для передачи в новый поток. Можно указать значение NULL.

(5) initflag определяет флаги, которые контролируют начальное состояние нового потока. Можно указать 0 для немедленного запуска, иначе CREATE_SUSPENDED для создания потока в приостановленном состоянии (после чего используйте ResumeThread для выполнения потока).

(6) thrdaddr определяет указатель на 32-битную переменную, которая получает идентификатор потока. Если NULL, то не используется.

Возвращаемое значение:

Если функция завершается успешно, возвращается дескриптор созданного потока.

Если функция завершается с ошибкой, возвращается 0.

Пример (C++).

Запускаем второй поток на выполнение и ждем его на протяжении времени INFINITE. Второй поток увеличивает счетчик от 0 до 10 миллионов, спит 2 секунды и завершается.

#include <iostream>

#include <windows.h>

using namespace std;

unsigned Counter = 0; /// Счетчик

unsigned __stdcall SecondThreadFunc(void* pArguments) {

cout << "Вошли во второй поток\n";

while ( Counter < 10000000 )

Counter++; /// Счетчик увеличиваем

Sleep(2000); /// Дополнительно спим

cout << "Выходим из второго потока\n";

_endthreadex(0);

return 0;

}

int main() {

setlocale(LC_ALL, "Russian"); /// Русский язык

HANDLE hThread; /// Дескриптор

unsigned threadID; /// ID потока

cout << "Создаем второй поток\n";

hThread = (HANDLE) _beginthreadex(NULL, 0, &SecondThreadFunc, NULL, 0, &threadID);

WaitForSingleObject(hThread, INFINITE); /// Ждем, сколько можем; 2 секунды точно должны ждать — в функции Sleep(2000)

cout << "Счетчик должен быть 1000000; Смотрим -> " << Counter << '\n';

CloseHandle(hThread);

return 0;

}