Дао Потоков
_beginthread()
&
CreateThread()
Хочу услышать мнения бывалых по поводу этих ф-ций
когда какую использовать.... В чем отличия... и так далее...
Нашел в сях++ две ф-ции создания потоков
_beginthread()
&
CreateThread()
Хочу услышать мнения бывалых по поводу этих ф-ций
когда какую использовать.... В чем отличия... и так далее...
Обе функции не имеют отношения к оригинальному С++.
CreateThread - это функция Win32 API,
_beginthread - это функция MS расширения C++.
Если ты используешь в коде что-нибудь из CRT (а ведь однозначно используешь), то лучше применять _beginthread.
A thread in an executable that calls the C run-time library (CRT) should use the _beginthread and _endthread functions for thread management rather than CreateThread and ExitThread; this requires the use of the multi-threaded version of the CRT. It is safe to call CreateThread and ExitThread from a thread in a DLL that links to the static CRT as long as the thread does not call the DisableThreadLibraryCalls function.
Читал когда-то статью Рихтера, где анализировался код СreateThread() и рекомендовалось ее не использовать
Не зря MS разработали _beginthread() и _beginthreadex().
Хотелось бы из этого потока обращаться к данным класса, неохото засовывать их все в структуру и передовать в поток еще и указатель на нее.
Хотя в любом случае придется синхронизировать обращения потоков к этим данным X)-
Функция д.б. unsigned __stdcall, а общие данные д.б. volatile
Можно.
Функция д.б. unsigned __stdcall, а общие данные д.б. volatile
Забыл добавить:
unsigned __stdcall - это если запускаешь с пом. _beginthreadex(). в других - иначе, см. описание
Забыл добавить:
unsigned __stdcall - это если запускаешь с пом. _beginthreadex(). в других - иначе, см. описание
Кроме этого метод должен быть объявлен, как static, а это значит, что указатель на экземпляр класса все же придется передавать специально. В данном случае отличие от использования просто функции практически нет.
А можно ли в качестве точки старта нового потока указать функцию-член класса?
Можно , но не нужно, это накладывает ограничения на ф-цию. Ведь ф-ция потока имеет параметр указатель. Вот туда передай указатель на екземпляр класа, и вызывай уже ф-цию через него.
{
public:
void Potok();
}
DWORD Potok(void *obj)
{
reinterpret_cast<CMyClass *>(obj)->Potok();
return 0;
}
int WinMain(...)
{
DWORD id;
CMyClass cl;
CreateThread(0, 0, ::Potok, &cl, 0, &id);
}
{
public:
void Potok();
}
DWORD Potok(void *obj)
{
reinterpret_cast<CMyClass *>(obj)->Potok();
return 0;
}
int WinMain(...)
{
DWORD id;
CMyClass cl;
CreateThread(0, 0, ::Potok, &cl, 0, &id);
}
Только логичнее сделать функцию DWORD Potok(void *obj) статическим методом всё того же класса, а пускать поток лучше с помощью _beginthread, а не CreateThread.
А еще интересно как лучше их потом убивать? Из основного потока имеется ввиду.
Убивать никого нельзя, это смертный грех.
Потоку надо дать понять, что он больше никому не нужен, пусть покончит жизнь суицидом.
Говоря нормально, из основного потока выставляется некоторый флаг, в дочернем потоке этот флаг переодически проверяется, и как только флаг будет выставлен поток сам корректно завершается.
А убивать поток - это плохая практика, ты ведь в штатном режиме не терминируешь программы.
А еще интересно как лучше их потом убивать? Из основного потока имеется ввиду.
HANDLE hThread, // handle to thread
DWORD dwExitCode // exit code
);
При этом нужно быть осторожным-все выделенные и занятые в thread ресурсы остаются занятыми.
Говоря нормально, из основного потока выставляется некоторый флаг, в дочернем потоке этот флаг переодически проверяется, и как только флаг будет выставлен поток сам корректно завершается.
У меня при этом возникла некоторая проблема. Хотя наверно это уже оффтоп, вобщем у меня там цикл:
{
...
}
вобщем прога работает с сокетом и является сервером.
Так вот когда к серваку никто не конектится, то accept видимо не возвращает управления и поток не может проверить переменную flag второй раз :)
К стати, если кому то интересно поток завершается вызовом функции void _endthread(). Кажется она вызывается автоматически при выполнении return.
У меня при этом возникла некоторая проблема. Хотя наверно это уже оффтоп, вобщем у меня там цикл:
{
...
}
вобщем прога работает с сокетом и является сервером.
Так вот когда к серваку никто не конектится, то accept видимо не возвращает управления и поток не может проверить переменную flag второй раз :)
К стати, если кому то интересно поток завершается вызовом функции void _endthread(). Кажется она вызывается автоматически при выполнении return.
Напр. пошли сам себе сообщение
Напр. пошли сам себе сообщение
В смысле создать еще один сокет и с него законектится к самому себе? Както геморно получается. А другого пути нет?
А другого пути нет?
Использовать асинхронные сокеты.
Использовать асинхронные сокеты.
А так же не использовать в качестве условия accept(...) - для работы с сокетом в потоке проще обрабатывать события сокета.