请问如何创建一个线程及为创建的线程编写代码?请给出示例代码。多谢!

解决方案 »

  1.   

    See the link below, so many samples there, FYI: http://www.codeproject.com/threads/#Threads
      

  2.   

    什么意思?MSDN上的例子就很好啊。
    Creating Threads
    The CreateThread function creates a new thread for a process. The creating thread must specify the starting address of the code that the new thread is to execute. Typically, the starting address is the name of a function defined in the program code. This function takes a single parameter and returns a DWORD value. A process can have multiple threads simultaneously executing the same function. The following example demonstrates how to create a new thread that executes the locally defined function, ThreadFunc. #include <windows.h>
    #include <conio.h>DWORD WINAPI ThreadFunc( LPVOID lpParam ) 

        char szMsg[80];    wsprintf( szMsg, "Parameter = %d.", *(DWORD*)lpParam ); 
        MessageBox( NULL, szMsg, "ThreadFunc", MB_OK );    return 0; 

     
    VOID main( VOID ) 

        DWORD dwThreadId, dwThrdParam = 1; 
        HANDLE hThread; 
        char szMsg[80];    hThread = CreateThread( 
            NULL,                        // no security attributes 
            0,                           // use default stack size  
            ThreadFunc,                  // thread function 
            &dwThrdParam,                // argument to thread function 
            0,                           // use default creation flags 
            &dwThreadId);                // returns the thread identifier 
     
       // Check the return value for success. 
     
       if (hThread == NULL) 
       {
          wsprintf( szMsg, "CreateThread failed." ); 
          MessageBox( NULL, szMsg, "main", MB_OK );
       }
       else 
       {
          _getch();
          CloseHandle( hThread );
       }

    For simplicity, this example passes a pointer to a value as an argument to the thread function. This could be a pointer to any type of data or structure, or it could be omitted altogether by passing a NULL pointer and deleting the references to the parameter in ThreadFunc. It is risky to pass the address of a local variable if the creating thread exits before the new thread, because the pointer becomes invalid. Instead, either pass a pointer to dynamically allocated memory or make the creating thread wait for the new thread to terminate. Data can also be passed from the creating thread to the new thread using global variables. With global variables, it is usually necessary to synchronize access by multiple threads. For more information about synchronization, see Synchronizing Execution of Multiple Threads. In processes where a thread might create multiple threads to execute the same code, it is inconvenient to use global variables. For example, a process that enables the user to open several files at the same time can create a new thread for each file, with each of the threads executing the same thread function. The creating thread can pass the unique information (such as the file name) required by each instance of the thread function as an argument. You cannot use a single global variable for this purpose, but you could use a dynamically allocated string buffer. The creating thread can use the arguments to CreateThread to specify the following: The security attributes for the handle to the new thread. These security attributes include an inheritance flag that determines whether the handle can be inherited by child processes. The security attributes also include a security descriptor, which the system uses to perform access checks on all subsequent uses of the thread's handle before access is granted. 
    The initial stack size of the new thread. The thread's stack is allocated automatically in the memory space of the process; the system increases the stack as needed and frees it when the thread terminates. 
    A creation flag that enables you to create the thread in a suspended state. When suspended, the thread does not run until the ResumeThread function is called. 
    You can also create a thread by calling the CreateRemoteThread function. This function is used by debugger processes to create a thread that runs in the address space of the process being debugged. 
      

  3.   

    楼上,我用你的办法,为什么编译会出一个错误啊?
    D:\APPLICATIONS\Sampling\SamplingView.cpp(232) : error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned int (void *)' to 'unsigned long (__stdcall *)(void *)'
      

  4.   

    强制类型转换一下就好了
    (LPTHREAD_START_ROUTINE)ThreadFunc
      

  5.   

    如果都是全局的,就直接调用就好了
    如果是调用类的成员函数,就需要做一个强制类型转换;
    参考:
    bool CRecvThread::Create(CSzWinGateWayDlg *g_WinDlg)
    { AfxBeginThread(ThreadPutRevMsgToList,g_WinDlg,THREAD_PRIORITY_NORMAL); return 1;
    }
    UINT ThreadPutRevMsgToList(LPVOID param)
    {
    CSzWinGateWayDlg * p_Win = (CSzWinGateWayDlg * )param;
             p_Win.aaa();                  //调用CSzWinGateWayDlg类的函数
    }
      

  6.   

    如果使用vc编译推荐使用_beginthread,_endthread或_beginthreadex,_endthreadex函数,这是vc ++运行库函数它封装了相关的API,比起直接使用CreateThread等函数安全,具体用法请参阅MSDN相关文档.
      

  7.   

    摘自MSDN:_beginthread, _beginthreadex
    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 
    Security descriptor for new thread; 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.Res
    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.LibrariesMultithreaded 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.Example
    The following example uses _beginthread and _endthread./* BEGTHRD.C illustrates multiple threads using functions:
     *
     *      _beginthread            _endthread
     *
     *
     * This program requires the multithreaded library. For example,
     * compile with the following command line:
     *     CL /MT /D "_X86_" BEGTHRD.C
     *
     * If you are using the Visual C++ development environment, select the 
     * Multi-Threaded runtime library in the compiler Project Settings 
     * dialog box.
     * 
     */
      

  8.   


    #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 */void 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();
    }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./* 
       begthrdex.cpp
       Compile options needed: Default options for a multithreaded console
       application. You need to compile the code as a .CPP file.
    */#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;
    } void 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 has terminated. 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 );
    }