|
Программирование >> Формирование пользовательского контейнера
90 Глава 3 значение равно нулю, новый поток получит стек, по размеру равный создаваемому потоку. В этом случае стек будет расширяться при необходимости (указание нуля для размера стека - стандартный прием). Каждый поток выполнения начинается с вызова внутри создаваемого процесса функции, называемой функцией потока (thread function). Выполнение потока продолжается до возврата функции потока в вызывающую программу. Адрес этой функции (это точка входа потока (thread entry)) задается в параметре threadFunc. Все функции потока должны соответстювать следующему прототипу: DWORD WINAPI threadfunc(LPVOID param) ; Любой аргумент, который вы хотите передать потоку, указывается в параметре param функЦИИ CreateThread (). ФункЦИЯ ПОТОКа ПОЛучает ЭТО 32-битное значение в виде параметра. Его можно использовать для разных целей. Функция возвращает код состояния (exit status). Параметр flags определяет состояние выполнения потока. Если он равен нулю, то поток начнет выполняться немедленно. Если его значение - CREATE susPEND, ПОТОК создастся В отложснном СОСТОЯНИИ, В ожидании выполнения (он может начать выполнение с помощью вызова функции ResumeThreadO, обсуждаемой позднее). Идентификатор, связанный с потоком, возвращается в длинном целом, на которое указывает параметр threadiD. Функция возвращает дескриптор потока при успешном завершении или NULL при возникновении ошибки. Дескриптор потока (thread handle) можно уничтожить явно, вызвав функцию cioseThreado. В противном случае он будет уничтожен автоматически, когда закончится родительский процесс. Как уже отмечалось, поток выполнения завершается, когда соответствующая ему функция потока возвращается в вызывающую программу. Процесс может завершить поток самостоятельно с помощью функций TerminateThreadO И ExitThread( ), ПрОТОТИПЫ КОТОрЫХ ПрИВСДСНЫ даЛСС. BOOL TerminateThread(HANDLE thread, DWORD status); VOID ExitThread(DWORD status); У функции TerminateThreadO параметр thread - ЭТО дескриптор завершаемого потока, функция ExitThreadO может завершить только тот поток, который ее вызывает. Параметр status в обеих функциях - статус завершения. Функция TerminateThreadO возвращает ненулсвое значение при успешном завершении и нулевое в противном случае. Вызов функции ExitThreadO функционально эквивалентен нормальному завершению функиии потока. Это значит, что стек соответствующим образом сброшен. Если же поток завершается с помошью функции TerminateThreadO, он останавливается немедленно и не выполняет никакой специальной очистки iOnOTCNHOCTb 91 стека. Кроме того, последний вариант завершения может остановить поток время выполнения важной операции. Поэтому лучше (да и легче) дать П(УГ0КУ завершиться нормально, когда вернется в программу его функция. Альтернативы API-функций создания и завершения потока, предлагаемые компилятором Visual С++ Несмотря на то, что функции CreateThread () И ExitThreadO являются API-функциями операционной системы Windows для создания и завершения потока, мы не будем их использовать в этой главе. Применяемые с компилятором Visual С++ (и, возможно, с другими Windows-совместимыми компиляторами), они вызывают утечки памяти, потерю небольшого объема памяти. В среде программирования Visual С++, если многопоточная программа использует совместно со стандартной библиотекой функций C/C++ функции CreateThread о И ExitThreadO, теряетСЯ небольшое КОЛИЧестВО памяти (если в вашей программе не применяется стандартная библиотека функций, то таких потерь не возникает). Для устранения этой проблемы вам следует использовать функции, определенные в стандартной библиотеке Visual С++ для создания и остановки потоков, вместо описанных ранее API-функций. Эти функции аналогичны функциям CreateThread() И ExitThreadO, но не приводят к потерям памяти. Примечание Если вы пользуетесь другим компилятором, не Visual С++, прочитайте документацию, чтобы выяснить, нужно ли вам заменить функции CreateThread () и ExitThread (), И как ЭТО сделать. Альтернативные функции Visual С++ - beginthreadexO и endthreadex (). Обеим требуется заголовочный файл <process.h>. Далее приводится прототип для функции beginthreadex (). uintptr t beginthreadex(void *secAttr,unsigned stackSize, unsigned ( stdcall *threadFunc)(void *), void *parain,unsigned flags, unsigned *threadID); ВИДНО, параметры функции beginthreadex о очснь ПОХОЖИ на параметры функции CreateThread (). Более ТОГО, у НИХ ТО жс назначение, что и у параметров функции createThread о. Параметр secAttr - это указатель на множество атрибутов защиты, принадлежащих потоку. Если указатель SecAttr равен null, то используется дескриптор защиты по умолчанию. 1*азмер в байтах стека для нового потока передается в параметре stacksize. 92 Глава 3 Если этот размер задан нулевым, то стек потока равен размеру основного потока в процессе, который его создает. Адрес функции потока (которая является точкой входа для потока) указывается в параметре threadFunc. Для функЦИИ beginthreadex() функиия по- тока имеет следующий прототип: unsigned stdcall threadfunc (void *param) ; Этот прототип функционально эквивалентен прототипу функции потока для createThreado, но в нсм используются другие имсна типов. Любой аргумент, который вы хотите передать новому потоку, описывается в параметре с именем param. Параметр flags определяет состояние выполнения потока. Если он равен нулю, то поток начинает выполняться немедленно. Если его значение равно константе create suspend, поток создается в отложенном состоянии, ожидая выполнения (его можно начать, вызвав функцию ResumeThreadO). Идентификатор, связанный с потоком, возвращается в двойном слове, на которое указывает параметр threadiD. Функция при успещном выполнении возвращает дескриптор потока, а при возникновении ощибки 0. Тип uintptr t определяет тип Visual С++, способный хранить указатель или дескриптор. Далее показан прототип функции endthreadex (): Void endthreadex(unsigned status); Функция действует так же, как ExitThreadO, останавливая поток и возвращая статус его заверщения. Поскольку компилятор Visual С++ - наиболее часто используемый компилятор в операционной системе Windows, в примерах этой главы будут применяться функции beginthreadex() и endthreadex(), а нс Эквивалентные им API-функции. Если вы используете другой компилятор, не Visual С++, просто замените их функциями CreateThread() И ExitThreadO. Применяя функции beginthreadex () и endthreadex О, помнитс о необходимости при компоновке использовать библиотеку поддержки многопоточности. Способы ее подключения могут быть разными у различных компиляторов. Если вы применяете компилятор Visual С++, работающий в режиме командной строки, включите в строку ключ -мт. В среде программирования Visual С++6 выполните следующие действия. 1. Выберите в меню команду Project Settings (Проект Установки). 2. В открывшемся окне перейдите на вкладку С\С++. 3. В списке Category (Категория) выберите Code Generation (Генерация кода). 4. В списке Use Runtime Library (Использовать динамическую библиотеку) укажите Multithreaded (Поддерживающая многопоточность).
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |