Возвращаемое значение
В случае успеха каждая из этих функций возвращает дескриптор во вновь созданный поток; однако если вновь созданный поток выполняет выход слишком быстро, может не возвращать допустимый дескриптор. (См. обсуждение в разделе «Заметки».) При возникновении ошибки возвращает -1L, а параметр имеет значение , если слишком много потоков, значение , если аргумент является недопустимым или размер стека неверен, либо значение , если недостаточно ресурсов (например, памяти). При возникновении ошибки возвращает 0, а и заданы.
Если параметр имеет значение , вызывается обработчик недопустимых параметров, как описано в разделе . Если продолжение выполнения разрешено, эти функции устанавливают для значение и возвращают -1.
Дополнительные сведения об этих и других кодах возврата см. в разделе,, и .
Дополнительные сведения о см. в разделе .
Комментарии
Функция создает поток, который начинает выполнение процедуры в . В процедуре необходимо использовать (для машинного кода) или соглашение о вызовах (для управляемого кода); там не должно быть возвращаемого значения. При возврате потока из этой процедуры он завершается автоматически. Дополнительные сведения о потоках см. в разделе Поддержка многопоточности для устаревшего кода (Visual C++).
похож на API Win32, который более близок к функции . имеет следующие отличия от :
-
имеет три дополнительных параметра: , и . Новый поток можно создать в приостановленном состоянии (с заданной безопасностью), а доступ к нему можно осуществлять с помощью , который является идентификатором потока.
-
Процедура в , передаваемая атрибуту , должна использовать (для машинного кода) или соглашение о вызовах (для управляемого кода) и должна возвращать код завершения потока.
-
возвращает при ошибке 0, а не -1L.
-
Поток, созданный с помощью, завершается вызовом метода .
Функция обеспечивает большую подконтрольность создания потока, чем . Функция также является более гибкой. Например, с помощью можно использовать сведения о безопасности, задавать исходное состояние потока (выполняемого или приостановленного) и получить идентификатор только что созданного потока. Можно также использовать дескриптор потока, возвращаемого методом , с помощью функций синхронизации API-интерфейса, что невозможно в случае с .
Безопаснее использовать , чем . Если поток, созданный , выполняет выход быстро, маркер, возвращаемый вызывающему объекту , может быть недопустим или указывать на другой поток. Однако маркер, который возвращается , должен быть закрыт вызывающим объектом , поэтому это однозначно допустимый маркер, если не возвращает ошибку.
Можно вызвать или явно завершить поток, однако или вызывается автоматически при возврате потока из подпрограммы, передаваемой в качестве параметра. Остановка потока вызовом метода или помогает обеспечить правильное восстановление ресурсов, выделяемых для потока.
автоматически закрывает дескриптор потока, тогда как этого не делает. Поэтому при использовании и не следует явно закрывать обработчик потока путем вызова API Win32. Это поведение отличается от API Win32 .
Примечание
Для исполняемого файла, связанного с Libcmt.lib, не следует вызывать функцию API Win32 , чтобы не помешать системе времени выполнения освобождать выделенные ресурсы. и освобождают выделенные ресурсы потока и затем вызывают метод .
Операционная система обрабатывает выделение стека, если или вызываются; не следует передавать адрес стека потоков любой из этих функций. Кроме того, аргумент может быть 0, в случае чего операционная система использует то же значение, что и стек, указанный для основного потока.
— это параметр для передачи только что созданному потоку. Как правило, это адрес элемента данных, например строки символов. может быть , если это не требуется, но и должно иметь некоторое значение для передачи в новый поток. Все потоки завершаются, если какой-либо поток вызывает метод , , или .
Языковой стандарт для нового потока инициализируется с использованием сведений о глобальном текущем языковом стандарте для каждого процесса. Если языковой стандарт для каждого потока включен с помощью вызова (глобально или только для новых потоков), поток может изменить свой языковой стандарт независимо от других потоков, вызвав или . Потоки, у которых нет установленного флага локали для каждого потока, могут влиять на сведения о языковых стандартах во всех других потоках, которые также не имеют установленного флага локали для каждого потока, а также всех вновь создаваемых потоков. Для получения дополнительной информации см. Locale.
Для кода, каждый из которых имеет две перегрузки. Один принимает собственный указатель функции соглашения о вызовах, а другой принимает указатель на функцию. Первый перегруженный метод не является безопасным для домена приложения и никогда таковым не будет. При написании кода необходимо убедиться, что новый поток входит в правильный домен приложения, прежде чем он будет получать доступ к управляемым ресурсам. Это можно сделать, например, с помощью функции. Вторая перегрузка является доменобезопасной; только что созданный поток всегда завершается в домене приложения вызывающего объекта или .
По умолчанию глобальное состояние этой функции ограничивается приложением. Чтобы изменить это, см. раздел глобальное состояние в CRT.
Remarks
The function creates a thread that begins execution of a routine at . The routine at must use the (for native code) or (for managed code) calling convention and should have no return value. When the thread returns from that routine, it is terminated automatically. For more information about threads, see Multithreading Support for Older Code (Visual C++).
resembles the Win32 API more closely than does. differs from in the following ways:
-
has three additional parameters: , , and . The new thread can be created in a suspended state, with a specified security, and can be accessed by using , which is the thread identifier.
-
The routine at that’s passed to must use the (for native code) or (for managed code) calling convention and must return a thread exit code.
-
returns 0 on failure, rather than -1L.
-
A thread that’s created by using is terminated by a call to .
The function gives you more control over how the thread is created than does. The function is also more flexible. For example, with , you can use security information, set the initial state of the thread (running or suspended), and get the thread identifier of the newly created thread. You can also use the thread handle that’s returned by with the synchronization APIs, which you cannot do with .
It’s safer to use than . If the thread that’s generated by exits quickly, the handle that’s returned to the caller of might be invalid or point to another thread. However, the handle that’s returned by has to be closed by the caller of , so it is guaranteed to be a valid handle if did not return an error.
You can call or explicitly to terminate a thread; however, or is called automatically when the thread returns from the routine that’s passed as a parameter. Terminating a thread with a call to or helps ensure correct recovery of resources that are allocated for the thread.
automatically closes the thread handle, whereas does not. Therefore, when you use and , do not explicitly close the thread handle by calling the Win32 API. This behavior differs from the Win32 API.
Note
For an executable file linked with Libcmt.lib, do not call the Win32 API so that you don’t prevent the run-time system from reclaiming allocated resources. and reclaim allocated thread resources and then call .
The operating system handles the allocation of the stack when either or is called; you don’t have to pass the address of the thread stack to either of these functions. In addition, the argument can be 0, in which case the operating system uses the same value as the stack that’s specified for the main thread.
is a parameter to be passed to the newly created thread. Typically, it is the address of a data item, such as a character string. can be if it is not needed, but and must be given some value to pass to the new thread. All threads are terminated if any thread calls , , , or .
The locale of the new thread is initialized by using the per-process global current locale info. If per-thread locale is enabled by a call to (either globally or for new threads only), the thread can change its locale independently from other threads by calling or . Threads that don’t have the per-thread locale flag set can affect the locale info in all other threads that also don’t have the per-thread locale flag set, as well as all newly-created threads. For more information, see Locale.
For code, and each have two overloads. One takes a native calling-convention function pointer, and the other takes a function pointer. The first overload is not application domain-safe and never will be. If you are writing code you must ensure that the new thread enters the correct application domain before it accesses managed resources. You can do this, for example, by using Function. The second overload is application domain-safe; the newly created thread will always end up in the application domain of the caller of or .
By default, this function’s global state is scoped to the application. To change this, see Global state in the CRT.
Return Value
If successful, each of these functions returns a handle to the newly created thread; however, if the newly created thread exits too quickly, might not return a valid handle. (See the discussion in the Remarks section.) On an error, returns -1L, and is set to if there are too many threads, to if the argument is invalid or the stack size is incorrect, or to if there are insufficient resources (such as memory). On an error, returns 0, and and are set.
If is NULL, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, these functions set to and return -1.
For more information about these and other return codes, see errno, _doserrno, _sys_errlist, and _sys_nerr.
For more information about , see Standard Types.
Управляемые потоки и подразделения COM
Управляемый поток может быть отмечен для указания того, что в нем будет размещаться однопотоковое или многопотоковое подразделение. (Дополнительные сведения об архитектуре потоков COM см. в статье Processes, Threads, and Apartments (Процессы, потоки и подразделения)). Методы GetApartmentState, SetApartmentState и TrySetApartmentState класса Thread возвращают и назначают состояние подразделения потока. Если состояние не задано, GetApartmentState возвращает .
Свойство можно задать, только когда поток находится в состоянии ; его можно задать только один раз для потока.
Если состояние подразделения не задано до запуска потока, этот поток инициализируется в качестве многопотокового подразделения (MTA). Поток метода завершения и все потоки, управляемые ThreadPool , являются многопотоковыми подразделениями.
Важно!
Для кода запуска приложения единственный способ управления состоянием подразделения заключается в применении MTAThreadAttribute или STAThreadAttribute к процедуре точки входа.
Управляемые объекты, предоставляемые интерфейсу COM, работают так, как если бы они агрегировали упаковщик в режиме свободного потока. Другими словами, их можно вызвать из любого подразделения COM в режиме свободного потока. В таком режиме не работают только управляемые объекты, производные от ServicedComponent или StandardOleMarshalObject.
В управляемом коде отсутствует поддержка SynchronizationAttribute , если только вы не используете контексты и контекстно-привязанные управляемые экземпляры. Если вы используете корпоративные службы, ваш объект должен быть производным от ServicedComponent (который сам является производным от ContextBoundObject).
Когда управляемый код вызывает COM-объекты, он всегда следует правилам COM. Другими словами, он выполняет вызов через прокси-серверы подразделения COM и оболочки контекста COM+ 1.0, как того требует OLE32.
Рождение процесса 2 kthreadd
Ранние интерфейсы kernel_create и daemonize
В ранних ядрах были предусмотрены интерфейсы kernel_create и daemonize, но этот механизм сложен в эксплуатации и делегирует все задачи ядру для выполнения.
Но этот механизм неэффективен и громоздок. Он сжимает все операции в ядре. Не было ли наше первоначальное намерение создать потоки ядра, чтобы разделять работу ядра и уменьшать накладные расходы ядра?
Механизм очереди работ
Поэтому после linux-2.6 предоставляются более удобные интерфейсы kthead_create и kthread_run, а создание потоков ядра откладывается и передается в рабочую очередь workqueue, см.,
Механизм очереди работ в Linux предназначен для упрощения создания потоков ядра. Через kthread_create поток ядра на самом деле не создается, но работа по созданию вставляется в очередь работ.In, затем вызовите интерфейс очереди работ для создания потока ядра. И количество потоков может быть создано в соответствии с количеством текущих системных процессоров, так что транзакции, обрабатываемые потоками, могут быть распараллелены. Workqueue — это простой и эффективный механизм в ядре, который, очевидно, упрощает создание демонов ядра и облегчает программирование пользователем.
Процесс 2 kthreadd
Но этот метод по-прежнему выглядит недостаточно элегантно, почему бы нам не передать работу по созданию потоков ядра специальному потоку ядра?
Таким образом, linux-2.6.22 представил процесс kthreadd, а затем превратился в процесс №2, который был создан вместе с процессом №1 при инициализации системы (конечно, это должно происходить через kernel_thread),, А затем превратился в настоящего строителя, создавшего поток ядра,См. Kthreaddс участием, В цикле он будет запрашивать рабочий списокЕсть ли поток ядра, который необходимо создать в потоке ядра, и наша операция через kthread_create просто добавляет задачу создания в очередь задач потока ядра kthread_create_list, а затем процесс kthreadd будет пробужден для выполнения реальной операции создания
Потоки ядра появятся в списке системных процессов, но в выводе ps команда имени процесса заключена в квадратные скобки, чтобы отличать ее от обычных процессов.
Как показано на рисунке ниже, мы можем видеть, что в системе все потоки ядра обозначены [], а идентификатор родительского процесса этих процессов равен 2, а родительский процесс процесса 2 kthreadd — это процесс 0
Волоконные функции
С волокнамииспользуются следующие функции.
Функция | Описание |
---|---|
конвертфибертосреад | Преобразует текущее волокное в поток. |
конвертсреадтофибер | Преобразует текущий поток в волокно. |
конвертсреадтофиберекс | Преобразует текущий поток в волокно. |
креатефибер | Выделяет объект Fiber, назначает его стек и настраивает выполнение, начиная с указанного начального адреса. |
креатефиберекс | Выделяет объект Fiber, назначает его стек и настраивает выполнение, начиная с указанного начального адреса. |
делетефибер | Удаляет существующее волокно. |
фиберпрок | Определяемая приложением функция, используемая с функцией креатефибер . |
флсаллок | Выделяет индекс оптоволоконного локального хранилища (ФЛС). |
флсфри | Освобождает индекс ФЛС. |
флсжетвалуе | Извлекает значение для указанного индекса ФЛС в вызываемом сегменте ФЛС Fiber. |
флссетвалуе | Сохраняет значение в слоте ФЛС в вызывающем Волоке для указанного индекса ФЛС. |
иссреадафибер | Определяет, является ли текущий поток волокным. |
свитчтофибер | Планирует волокно. |
0x03 О безопасности потоков
- Поскольку функции библиотеки времени выполнения C не были изначально предназначены для многопоточности, при использовании некоторых глобальных переменных библиотеки времени выполнения C следует отметить, что любой поток может изменять глобальные переменные (например, errno). В однопоточном случае проблем определенно нет, но в многопоточном Будет путаница, например, поток только что установил errno на передней ножке и готов к просмотру, но задняя ножка заменена другим потоком
- Это источник безопасности потоков C / C ++. Решение состоит в том, чтобы выделить независимое пространство глобальных переменных библиотеки времени выполнения C для каждого потока. Конечно, нам не нужно выполнять такую сложную работу. Вы можете использовать функцию безопасности потоков _beginthreadex. , Это действительно удобно.Эта функция автоматически выделяет глобальные переменные библиотеки времени выполнения C внутри, а затем вызывает CreateThread для создания потока после выделения, поэтому вам нужно только использовать _beginthreadex для создания потока в будущем.
- Пример выглядит следующим образом. Включенный файл заголовка — process.h. За исключением различных типов параметров, другие параметры, включая типы параметров и последовательность параметров, точно такие же, как при использовании CreateThread. Уловка заключается в том, что возвращаемое значение функции вызова потока изменяется с DWORD на unsigned
Фактически, функции _beginthreadex и _endthreadex имеют относительно простую версию, называемую _beginthread и _endthread; разница в том, что функция _beginthread не может возвращать идентификатор потока, а также не может устанавливать флаги безопасности (например, наследование и т. Д.), А _endthread не может возвращать поток для выхода. Код, вкратце, очень другой, пример следующий
Кроме того, существует малоизвестная проблема: дескриптор потока (MyThread) будет освобожден после вызова _beginthread, что означает, что созданный дескриптор потока не может быть использован после выполнения потока. Если функция CloseHandle вызывается снова Если вы закроете ручку, возникнет исключение, как показано ниже.
Преимущество этого в том, что это удобно для вызывающего (новичкам не нужно закрывать дескриптор и использовать другие сложные операции), но недостатком является то, что снижается контроль потока (дескриптора)
Examples
The following example uses and .
// crt_BEGTHRD.C // compile with: /MT /D "_X86_" /c // processor: x86 #include <windows.h> #include <process.h> /* _beginthread, _endthread */ #include <stddef.h> #include <stdlib.h> #include <conio.h> void Bounce( void * ); void CheckKey( void * ); // GetRandom returns a random integer between min and max. #define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min)) // GetGlyph returns a printable ASCII character value #define GetGlyph( val ) ((char)((val + 32) % 93 + 33)) BOOL repeat = TRUE; // Global repeat flag HANDLE hStdOut; // Handle for console window CONSOLE_SCREEN_BUFFER_INFO csbi; // Console information structure int main() { int param = ; int * pparam = ¶m; // Get display screen's text row and column information. hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); GetConsoleScreenBufferInfo( hStdOut, &csbi ); // Launch CheckKey thread to check for terminating keystroke. _beginthread( CheckKey, , NULL ); // Loop until CheckKey terminates program or 1000 threads created. while( repeat && param < 1000 ) { // launch another character thread. _beginthread( Bounce, , (void *) pparam ); // increment the thread parameter param++; // Wait one second between loops. Sleep( 1000L ); } } // CheckKey - Thread to wait for a keystroke, then clear repeat flag. void CheckKey( void * ignored ) { _getch(); repeat = ; // _endthread implied } // Bounce - Thread to create and control a colored letter that moves // around on the screen. // // Params: parg - the value to create the character from void Bounce( void * parg ) { char blankcell = 0x20; CHAR_INFO ci; COORD oldcoord, cellsize, origin; DWORD result; SMALL_RECT region; cellsize.X = cellsize.Y = 1; origin.X = origin.Y = ; // Generate location, letter and color attribute from thread argument. srand( _threadid ); oldcoord.X = region.Left = region.Right = GetRandom(csbi.srWindow.Left, csbi.srWindow.Right - 1); oldcoord.Y = region.Top = region.Bottom = GetRandom(csbi.srWindow.Top, csbi.srWindow.Bottom - 1); ci.Char.AsciiChar = GetGlyph(*((int *)parg)); ci.Attributes = GetRandom(1, 15); while (repeat) { // Pause between loops. Sleep( 100L ); // Blank out our old position on the screen, and draw new letter. WriteConsoleOutputCharacterA(hStdOut, &blankcell, 1, oldcoord, &result); WriteConsoleOutputA(hStdOut, &ci, cellsize, origin, ®ion); // Increment the coordinate for next placement of the block. oldcoord.X = region.Left; oldcoord.Y = region.Top; region.Left = region.Right += GetRandom(-1, 1); region.Top = region.Bottom += GetRandom(-1, 1); // Correct placement (and beep) if about to go off the screen. if (region.Left < csbi.srWindow.Left) region.Left = region.Right = csbi.srWindow.Left + 1; else if (region.Right >= csbi.srWindow.Right) region.Left = region.Right = csbi.srWindow.Right - 2; else if (region.Top < csbi.srWindow.Top) region.Top = region.Bottom = csbi.srWindow.Top + 1; else if (region.Bottom >= csbi.srWindow.Bottom) region.Top = region.Bottom = csbi.srWindow.Bottom - 2; // If not at a screen border, continue, otherwise beep. else continue; Beep((ci.Char.AsciiChar - 'A') * 100, 175); } // _endthread given to terminate _endthread(); }
Press any key to end the sample application.
The following sample code demonstrates how you can use the thread handle that’s returned by with the synchronization API . The main thread waits for the second thread to terminate before it continues. When the second thread calls , it causes its thread object to go to the signaled state. This allows the primary thread to continue running. This cannot be done with and , because calls , which destroys the thread object before it can be set to the signaled state.
// crt_begthrdex.cpp // compile with: /MT #include <windows.h> #include <stdio.h> #include <process.h> unsigned Counter; unsigned __stdcall SecondThreadFunc( void* pArguments ) { printf( "In second thread...\n" ); while ( Counter < 1000000 ) Counter++; _endthreadex( ); return ; } int main() { HANDLE hThread; unsigned threadID; printf( "Creating second thread...\n" ); // Create the second thread. hThread = (HANDLE)_beginthreadex( NULL, , &SecondThreadFunc, NULL, , &threadID ); // Wait until second thread terminates. If you comment out the line // below, Counter will not be correct because the thread has not // terminated, and Counter most likely has not been incremented to // 1000000 yet. WaitForSingleObject( hThread, INFINITE ); printf( "Counter should be 1000000; it is-> %d\n", Counter ); // Destroy the thread object. CloseHandle( hThread ); }
CWinThread::IsIdleMessage
Переопределите эту функцию, чтобы предотвратить ее вызов после создания определенных сообщений.
Комментарии
Реализация по умолчанию не вызывается после избыточных сообщений мыши и сообщений, созданных мигающими крышки.
Если приложение создало короткий таймер, будет вызываться часто, что приведет к проблемам с производительностью. Чтобы повысить производительность такого приложения, переопределите в классе, производном от приложения, проверку на наличие сообщений следующим образом:
Обработка таким образом повысит производительность приложений, использующих короткие таймеры.
CWinThread::OnIdle
Переопределите эту функцию-член для выполнения обработки во время простоя.
Параметры
Счетчик, увеличивающийся каждый раз, вызывается, когда очередь сообщений потока пуста. Этот счетчик сбрасывается в 0 каждый раз при обработке нового сообщения. С помощью параметра можно определить относительный срок простоя потока без обработки сообщения.
Возвращаемое значение
Ненулевое значение для получения более длительного времени обработки; 0, если не требуется больше времени на простое время обработки.
Комментарии
вызывается в цикле сообщений по умолчанию, если очередь сообщений потока пуста. Используйте переопределение для вызова собственных задач обработчика бездействия в фоновом режиме.
должен возвращать значение 0, чтобы указать, что дополнительное время простоя не требуется. Параметр увеличивается каждый раз, когда очередь сообщений пуста и сбрасывается в 0 каждый раз при обработке нового сообщения. В зависимости от этого числа можно вызывать различные подпрограммы бездействия.
Реализация по умолчанию этой функции члена освобождает временные объекты и неиспользуемые библиотеки динамической компоновки из памяти.
Эта функция-член используется только в потоках пользовательского интерфейса.
Так как приложение не может обрабатывать сообщения до тех пор, пока не будет возвращено, не выполняйте длительные задачи в этой функции.
Parameters
A handle to the process in which the thread is to be created. The handle must have the PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ access rights, and may fail without these rights on certain platforms. For more information, see
Process Security and Access Rights.
A pointer to a
SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread and determines whether child processes can inherit the returned handle. If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot be inherited. The access control lists (ACL) in the default security descriptor for a thread come from the primary token of the creator.
Windows XP: The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator. This behavior changed with Windows XP with SP2 and Windows Server 2003.
The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is 0 (zero), the new thread uses the default size for the executable. For more information, see
Thread Stack Size.
A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see
ThreadProc.
A pointer to a variable to be passed to the thread function.
The flags that control the creation of the thread.
Value | Meaning |
---|---|
The thread runs immediately after creation. | |
|
The thread is created in a suspended state, and does not run until the ResumeThread function is called. |
|
The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size. |
A pointer to a variable that receives the thread identifier.
If this parameter is NULL, the thread identifier is not returned.
Функции потока
В потокахиспользуются следующие функции.
Функция | Описание |
---|---|
аттачсреадинпут | Присоединяет механизм обработки ввода одного потока к другому потоку. |
креатеремотесреад | Создает поток, который выполняется в виртуальном адресном пространстве другого процесса. |
креатеремотесреадекс | Создает поток, который выполняется в виртуальном адресном пространстве другого процесса и дополнительно задает расширенные атрибуты, такие как сходство групп процессоров. |
CreateThread | Создает поток для выполнения в пределах виртуального адресного пространства вызывающего процесса. |
ExitThread | Завершает вызывающий поток. |
GetCurrentThread | Извлекает псевдо-обработчик для текущего потока. |
GetCurrentThreadId | Получает идентификатор потока вызывающего потока. |
жетекситкодесреад | Возвращает состояние завершения указанного потока. |
жетсреаддескриптион | Извлекает описание, назначенное потоку путем вызова SetThreadDescription. |
жетсреадграупаффинити | Возвращает соответствие группы процессоров указанному потоку. |
GetThreadId | Возвращает идентификатор потока указанного потока. |
жетсреадидеалпроцессорекс | Возвращает номер процессора идеального процессора для указанного потока. |
жетсреадинформатион | Извлекает сведения об указанном потоке. |
жетсреадиопендингфлаг | Определяет, имеет ли указанный поток ожидающие запросы ввода-вывода. |
жетсреадприорити | Возвращает значение приоритета для указанного потока. |
жетсреадприоритибуст | Возвращает состояние элемента управления повышением приоритета указанного потока. |
жетсреадтимес | Извлекает сведения о времени для указанного потока. |
опенсреад | Открывает существующий объект потока. |
куеридлепроцессорциклетиме | Возвращает время цикла для бездействующего потока каждого процессора в системе. |
куерисреадциклетиме | Возвращает время цикла для указанного потока. |
ResumeThread | Уменьшает значение счетчика приостановки потока. |
сетсреадаффинитимаск | Задает маску сходства процессоров для указанного потока. |
SetThreadDescription | Присваивает описание потоку. |
сетсреадграупаффинити | Задает сходство групп процессоров для указанного потока. |
сетсреадидеалпроцессор | Указывает предпочтительный процессор для потока. |
сетсреадидеалпроцессорекс | Задает идеальный процессор для указанного потока и при необходимости извлекает предыдущий идеальный процессор. |
сетсреадинформатион | Задает сведения для указанного потока. |
SetThreadPriority | Задает значение приоритета для указанного потока. |
сетсреадприоритибуст | Отключает возможность системы временно увеличивать приоритет потока. |
сетсреадстаккгуаранти | Задает гарантию стека для вызывающего потока. |
Sleep | Приостанавливает выполнение текущего потока в течение заданного интервала. |
слипекс | Приостанавливает текущий поток до тех пор, пока не будет выполнено указанное условие. |
SuspendThread | Приостанавливает указанный поток. |
свитчтосреад | Позволяет вызвавшему потоку передать выполнение другому потоку, готовому к использованию на текущем процессоре. |
TerminateThread | Завершает поток. |
среадпрок | Определяемая приложением функция, служащая начальным адресом для потока. |
TlsAlloc | Выделяет индекс локального хранилища потока (TLS). |
TlsFree | Освобождает индекс TLS. |
тлсжетвалуе | Получает значение в слоте TLS вызывающего потока для указанного индекса TLS. |
тлссетвалуе | Сохраняет значение в слоте TLS вызывающего потока для указанного индекса TLS. |
ваитфоринпутидле | Ожидает, пока указанный процесс не ждет ввода пользователя, не ожидая ввода, или до истечения интервала времени ожидания. |
Remarks
The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2,048 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue.
The new thread handle is created with the THREAD_ALL_ACCESS access right. If a security descriptor is not provided when the thread is created, a default security descriptor is constructed for the new thread using the primary token of the process that is creating the thread. When a caller attempts to access the thread with the OpenThread function, the effective token of the caller is evaluated against this security descriptor to grant or deny access.
The newly created thread has full access rights to itself when calling the GetCurrentThread function.
Windows Server 2003: The thread’s access rights to itself are computed by evaluating the primary token of the process in which the thread was created against the default security descriptor constructed for the thread. If the thread is created in a remote process, the primary token of the remote process is used. As a result, the newly created thread may have reduced access rights to itself when calling GetCurrentThread. Some access rights including THREAD_SET_THREAD_TOKEN and THREAD_GET_CONTEXT may not be present, leading to unexpected failures. For this reason, creating a thread while impersonating another user is not recommended.
If the thread is created in a runnable state (that is, if the CREATE_SUSPENDED flag is not used), the thread can start running before CreateThread returns and, in particular, before the caller receives the handle and identifier of the created thread.
The thread execution begins at the function specified by the lpStartAddress parameter. If this function returns, the DWORD return value is used to terminate the thread in an implicit call to the
ExitThread function. Use the
GetExitCodeThread function to get the thread’s return value.
The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the
GetThreadPriority and
SetThreadPriority functions to get and set the priority value of a thread.
When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting on the object.
The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to
CloseHandle.
The
ExitProcess,
ExitThread,
CreateThread,
CreateRemoteThread functions, and a process that is starting (as the result of a call by
CreateProcess) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means that the following restrictions hold:
- During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.
- Only one thread in a process can be in a DLL initialization or detach routine at a time.
- ExitProcess does not complete until there are no threads in their DLL initialization or detach routines.
_beginthreadex_endthreadexCreateThreadExitThreadCreateThread
Windows Phone 8.1: This function is supported for Windows Phone Store apps on Windows Phone 8.1 and later.
Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows Server 2012 R2, and later.