Сегодня я хотел бы рассказать как собственно создавать потоки функциями _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(). Но в большенстве случаев его использовать не обязательно, так как после окончания потока управление само передастся главной задаче.
Начну с того, что они позволяют использовать внутри потока все средства 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(). Но в большенстве случаев его использовать не обязательно, так как после окончания потока управление само передастся главной задаче.