Сегодня я хотел бы рассказать как собственно создавать потоки функциями _beginthread и _beginthreadex. Чем же лучше использование этих функций в замен стандартных средств из winapi?

Начну с того, что они позволяют использовать внутри потока все средства CRT-библиотеки, говоря простым языком, то можно использовать функции C++ такие как cout, fprint и т.д. В случае с CreateThread, которую рассматривать я не буду, можно использовать только WinApi средства.

Для начала рассмотрим прототип первой функции:

uintptr_t _beginthread(
void( *start_address )( void * ),
unsigned stack_size,
void *arglist
);

Первый аргумент это указатель на функцию, которая является точкой входа для самого потока. Сама функция должна выглядеть как:

void myThread(void* pParams)
{
...
}

Имя конечно же может быть любое.

Второй аргумент это начальный размер стека. Почти в любом случае его можно указать как 0. Тогда размер стека будет равен тому же, что и у главной задачи процесса.

С третьим все ещё легче, это аргументы функции потока, которые вполне могут быть как NULL. Или же выглядеть как (void*)(pParam) в случае с первой функцией.

Для полности приведу пример, который выводит 100 раз цифру 1 и 100 раз цифру 2.

#include #include <process.h>

void myThread(void* pParams)
{
for(int f=0;f<=100;f++){
std::cout << “1″;
}
_endthread();
}

int main()
{
_beginthread(myThread, 0, NULL);
for(int q=0;q<=100;q++){
std::cout << “2″;
}

system(”PAUSE”);
}

Теперь пора перейти к более функциональному собрату первой _beginthreadex. Она нужна в случае если вам понадобится в дополнение и возможности CreateThread. К примеру приостановление потока, чего нету в обычной _beginthread. Посмотрим на прототип:

unsigned long _beginthreadex(
void *Security,
unsigned StackSize,
unsigned (*StartAddress)(void*),
void *ArgList,
unsigned Initflag,
unsigned *ThrdAddr);

Теперь посмотрим на её аргументы:

Первый это указатель на дескриптор защиты. К сожалению это уже другой разговор и его я рассматривать не буду.

Второй аргумент это адрес стека. О нем речь шла ещё в первой функции.

Третий — сама функция задачи потока. О её уже было опять же рассказано в первой функции.

Четвертый — тоже уже было. см. _beginthread.

Пятый — это уже интереснее. Он используется для установки параметров задачи. Например если вы хотите создать поток в приостановленном состояние, то вам нужно установить параметр CREATE_SUSPENDED. Если не нужен можно поставить 0.

Ну и последний это адрес создания задачи.

Для выхода из потока используется _endthread(). Но в большенстве случаев его использовать не обязательно, так как после окончания потока управление само передастся главной задаче.