创建线程的两种方式

frankelin 2005-03-10 09:07:57
今天去面试,考官问我创建线程的两种方式,我知道由一个是CreateThread.另一种是什么呢???????
...全文
165 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Mr-Chen 2005-03-11
  • 打赏
  • 举报
回复
_beginthread((void (*)(void *))ReceiveMsg,0,(void *)&hwnd)
还可以用CWinThread* AfxBeginThread(...)
tudou614 2005-03-11
  • 打赏
  • 举报
回复
GZ
myroar123 2005-03-10
  • 打赏
  • 举报
回复
上面说的没错,但是都是英文,还麻烦的很
偶来大概说一下
一个就是你说的createthread()函数。这个函数比较正式一点,里面的参数就比较详细的安全性描述。还有一个就是_beginthread()函数了,这个是上面哪个函数的简化版本,windows出这个函数的原因是为了让这个函数可以运行在不同的平台下,所以它的参数都是c/c++的基础数据类型。它们若创建成功,都会返回创建的线程的HANDLE。2个函数里面都有一个参数就是传递的参数的指针。在普通的、简单的win32下的简单应用,建议用后面这个参数。在大一点的工程或者MFC程序应用中,最好用前面一个函数,关于线程有很多东西是直接和操作系统低层相关的,比如线程同步,共享内存等。建议好好深入一下,可以收获很多的
fireseed 2005-03-10
  • 打赏
  • 举报
回复

Example
The following example uses _beginthread and _endthread.

// crt_BEGTHRD.C
// compile with: /MT /D "_X86_" /c
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <conio.h>

void Bounce( void *ch );
void CheckKey( void *dummy );

/* GetRandom returns a random integer between min and max. */
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

BOOL repeat = TRUE; /* Global repeat flag and video variable */
HANDLE hStdOut; /* Handle for console window */
CONSOLE_SCREEN_BUFFER_INFO csbi; /* Console information structure */

int main()
{
CHAR ch = 'A';

hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

/* Get display screen's text row and column information. */
GetConsoleScreenBufferInfo( hStdOut, &csbi );

/* Launch CheckKey thread to check for terminating keystroke. */
_beginthread( CheckKey, 0, NULL );

/* Loop until CheckKey terminates program. */
while( repeat )
{
/* On first loops, launch character threads. */
_beginthread( Bounce, 0, (void *) (ch++) );

/* Wait one second between loops. */
Sleep( 1000L );
}
}

/* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */
void CheckKey( void *dummy )
{
_getch();
repeat = 0; /* _endthread implied */

}

/* Bounce - Thread to create and and control a colored letter that moves
* around on the screen.
*
* Params: ch - the letter to be moved
*/
void Bounce( void *ch )
{
/* Generate letter and color attribute from thread argument. */
char blankcell = 0x20;
char blockcell = (char) ch;
BOOL first = TRUE;
COORD oldcoord, newcoord;
DWORD result;


/* Seed random number generator and get initial location. */
srand( _threadid );
newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );
newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );
while( repeat )
{
/* Pause between loops. */
Sleep( 100L );

/* Blank out our old position on the screen, and draw new letter. */
if( first )
first = FALSE;
else
WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord, &result );
WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord, &result );

/* Increment the coordinate for next placement of the block. */
oldcoord.X = newcoord.X;
oldcoord.Y = newcoord.Y;
newcoord.X += GetRandom( -1, 1 );
newcoord.Y += GetRandom( -1, 1 );

/* Correct placement (and beep) if about to go off the screen. */
if( newcoord.X < 0 )
newcoord.X = 1;
else if( newcoord.X == csbi.dwSize.X )
newcoord.X = csbi.dwSize.X - 2;
else if( newcoord.Y < 0 )
newcoord.Y = 1;
else if( newcoord.Y == csbi.dwSize.Y )
newcoord.Y = csbi.dwSize.Y - 2;

/* If not at a screen border, continue, otherwise beep. */
else
continue;
Beep( ((char) ch - 'A') * 100, 175 );
}
/* _endthread given to terminate */
_endthread();
}
Input
press any key to end
The following sample code demonstrates how you can use the thread handle returned by _beginthreadex with the synchronization API WaitForSingleObject. The main thread waits for the second thread to terminate before it continues. When the second thread calls _endthreadex, it causes its thread object to go to the signaled state. This allows the primary thread to continue running. This cannot be done with _beginthread and _endthread, because _endthread calls CloseHandle, destroying 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( 0 );
return 0;
}

int main()
{
HANDLE hThread;
unsigned threadID;

printf( "Creating second thread...\n" );

// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &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 );
}
Output
Creating second thread...
In second thread...
Counter should be 1000000; it is-> 1000000
See Also
Process and Environment Control Routines | _endthread | abort | exit | Run-Time Routines and .NET Framework Equivalents



--------------------------------------------------------------------------------

Send feedback on this topic to Microsoft

© Microsoft Corporation. All rights reserved.
fireseed 2005-03-10
  • 打赏
  • 举报
回复
Run-Time Library Reference

_beginthread, _beginthreadexSee Also
Process and Environment Control Routines | _endthread | abort | exit | Run-Time Routines and .NET Framework Equivalents
Requirements
Routine Required header Compatibility
_beginthread <process.h> Win 98, Win Me, Win NT, Win 2000, Win XP
_beginthreadex <process.h> Win 98, Win Me, Win NT, Win 2000, Win XP

For additional compatibility information, see Compatibility in the Introduction.

Libraries

Multithreaded versions of the C run-time libraries only.

To use _beginthread or _beginthreadex, the application must link with one of the multithreaded C run-time libraries.
Create a thread.

uintptr_t _beginthread(
void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist
);
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
Parameters
start_address
Start address of routine that begins execution of new thread.
stack_size
Stack size for new thread or 0.
arglist
Argument list to be passed to new thread or NULL.
security
Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If NULL, the handle cannot be inherited. Must be NULL for Windows 95 applications.
initflag
Initial state of new thread (0 for running or CREATE_SUSPENDED for suspended); use ResumeThread to execute the thread.
thrdaddr
Points to a 32-bit variable that receives the thread identifier.
Return Value
If successful, each of these functions returns a handle to the newly created thread. _beginthread returns –1L on an error, in which case errno is set to EAGAIN if there are too many threads, or to EINVAL if the argument is invalid or the stack size is incorrect. _beginthreadex returns 0 on an error, in which case errno and _doserrno are set.

See Standard Types for more information on uintptr_t.

See _doserrno, errno, _sys_errlist, and _sys_nerr for more information on these and other return codes.

Remarks
The _beginthread function creates a thread that begins execution of a routine at start_address. The routine at start_address must use the __cdecl calling convention and should have no return value. When the thread returns from that routine, it is terminated automatically. For more information on threads, see Multithreading.

_beginthreadex resembles the Win32 CreateThread API more closely than _beginthread does. _beginthreadex differs from _beginthread in the following ways:

_beginthreadex has three additional parameters: initflag, security, threadaddr. The new thread can be created in a suspended state, with a specified security (Windows NT only), and can be accessed using thrdaddr, which is the thread identifier.
The routine at start_address passed to _beginthreadex must use the __stdcall calling convention and must return a thread exit code.
_beginthreadex returns 0 on failure, rather than –1L.
A thread created with _beginthreadex is terminated by a call to _endthreadex.
The _beginthreadex function gives you more control over how the thread is created than _beginthread does. The _endthreadex function is also more flexible. For example, with _beginthreadex, 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 are also able to use the thread handle returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.

It is safer to use _beginthreadex than _beginthread. If the thread spawned by _beginthread exits quickly, the handle returned to the caller of _beginthread may be invalid or, worse, point to another thread. However, the handle returned by _beginthreadex has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if _beginthreadex did not return an error.

You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter. Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.

_endthread automatically closes the thread handle (whereas _endthreadex does not). Therefore, when using _beginthread and _endthread, do not explicitly close the thread handle by calling the Win32 CloseHandle API. This behavior differs from the Win32 ExitThread API.

Note For an executable file linked with LIBCMT.LIB, do not call the Win32 ExitThread API; this prevents the run-time system from reclaiming allocated resources. _endthread and _endthreadex reclaim allocated thread resources and then call ExitThread.
The operating system handles the allocation of the stack when either _beginthread or _beginthreadex is called; you do not need to pass the address of the thread stack to either of these functions. In addition, the stack_size argument can be 0, in which case the operating system uses the same value as the stack specified for the main thread.

arglist 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. arglist may be NULL if it is not needed, but _beginthread and _beginthreadex must be provided with some value to pass to the new thread. All threads are terminated if any thread calls abort, exit, _exit, or ExitProcess.

Requirements
Routine Required header Compatibility
_beginthread <process.h> Win 98, Win Me, Win NT, Win 2000, Win XP
_beginthreadex <process.h> Win 98, Win Me, Win NT, Win 2000, Win XP

For additional compatibility information, see Compatibility in the Introduction.

Libraries

Multithreaded versions of the C run-time libraries only.

To use _beginthread or _beginthreadex, the application must link with one of the multithreaded C run-time libraries.

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧