Windows Thread survival (1) About _ beginthreadex, _ beginthread and createthreadmfc multithreading and thread synchronization

Source: Internet
Author: User
Document directory
  • 1. _ beginthread and _ beginthreadex
  • 2. afxbeginthread and createthread of MFC

I. Thread Creation

When a windows thread is created, it first creates a thread kernel object, which is a small data structure through which the operating system manages threads. The new thread can access all the handles of the Process kernel objects, all the memory in the process, and the stacks of other threads in the same process.

The following methods are available for creation:

  1. Createthread (...) (do not use the API provided by the operating system)
  2. _ Beginthread (...)
  3. _ Beginthreadex (...)
  4. Afxbeginthread (...) (the interface provided by MFC)

First declare a thread function, prototype:

DWORD FunThread(LPVOID pParam);
1. createthread ()

This function is provided by the operating system. The prototype is as follows:

HANDLE WINAPI CreateThread(  _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes ,  _In_       SIZE_T dwStackSize ,  _In_       LPTHREAD_START_ROUTINE lpStartAddress,  _In_opt_   LPVOID lpParameter,  _In_       DWORD dwCreationFlags,  _Out_opt_  LPDWORD lpThreadId );

Note:

Header Library DLL
WINBASE. h Kernel32.lib Kernel32.dll

 

 

Parameters:

Lpthreadattributes: PointSecurity_attributesThe pointer of the struct to record the thread's security description. Determines whether the sub-process can inherit the returned handle. If it is null, the default security level (Thread_priority_normal), And the return handle cannot be inherited.
Dwstacksize: Specifies the thread stack size. If it is 0, it indicates that the stack uses the default size.
Lpstartaddress: thread function pointer
Lpparameter: thread function parameters
Dwcreationflags: 0: indicates that the thread runs immediately after creation; create_suspend: indicates that the thread is suspended after creation. At this time, you can modify the thread attributes and wake up with resumethread;
Lpthreadid: a pointer to threadid. if you pay attention to the thread ID, the value is passed. Otherwise, null is set.

Return Value:

Create a thread handle;

If creation fails, null is returned and an error can be captured using getlasterror;

The createthread function is also provided in MFC, which is a method of the cwinthread class, as follows:

BOOL CreateThread(   DWORD dwCreateFlags = 0,   UINT nStackSize = 0,   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

The parameter has the same meaning as the return value. The call method is as follows:

CWinThread thread1;thread1.CreateThread();

It must be noted that when dwcreateflags is set to create_suspend, it must be awakened through cwinthread: resumethread.

2. _ beginthread (), _ beginthreadex ()

Prototype:

unsigned long _beginthread(         void( __cdecl *start_address )( void * ),         unsigned stack_size, void *arglist );unsigned long _beginthreadex(         void *security,         unsigned stack_size,         unsigned ( __stdcall *start_address )( void * ),         void *arglist,         unsigned initflag,         unsigned *thrdaddr );            

Note:

Header Library
Process. h Libcmt. Lib msvcrt. Lib

 

 

The parameter has the same meaning as the above createthread;

Comparison:

1. In _ beginthread, the thread function is called as _ cdecl, and no return value is returned. _ beginthreadex is _ stdcall and has a return value;

2. _ beginthreadex initflag is equivalent to dwcreationflags in createthread, and thrdaddr is equivalent to lpthreadid

3. In implementation, _ beginthreadex controls a _ tiddata thread data block, which stores many attributes of the thread function address and parameters, and then indirectly calls createthread (...);

4. _ beginthread requires fewer parameters;

3. afxbeginthread ()

The interfaces provided by MFC provide two different types of threads, namely, the worker thread and the user interface thread. You can simply understand that the user interface thread contains the user interface and has its own message queue, the worker thread is used for computing;

Cwinthread * afxbeginthread (afx_threadproc pfnthreadproc, // thread function pointer, function prototype: uint _ cdecl fnthread (lpvoid pparam); lpvoid pparam, // thread function parameter int npriority = priority, // priority, setthreadpriority uint nstacksize = 0, // stack size, unit: bytes. If it is 0, DWORD dwcreateflags = 0 by default. // create_suincluded: suspended after creation; 0: Run lpsecurity_attributes lpsecurityattrs = NULL immediately after creation. // a pointer to the security_attributes structure. If it is null, it indicates the default security attribute ); // create a worker thread cwinthread * afxbeginthread (cruntimeclass * pthreadclass, // point to interface class pointer, inherited from cwinthread int npriority = thread_priority_normal, uint nstacksize = 0, DWORD dwcreateflags = 0, lpsecurity_attributes lpsecurityattrs = NULL); // create a user interface thread

Note:

Header
Afxwin. h

 

 

4. Comparison between 1. _ beginthread and _ beginthreadex
  1. In implementation, _ beginthreadex controls a _ tiddata thread data block, which stores many attributes of the thread function address and parameters, and then indirectly calls createthread (...);
  2. _ Beginthread has few parameters and has limitations;
2. afxbeginthread and createthread of MFC
  1. Afxbeginthread is created in one step, and then the thread runs immediately
  2. Cwinthread: createthread is created in two steps, but it stores the thread object, which can be used between the continuous thread creation and the end of running (UseCreatethreadIf you want to reuse the thread object between successive creation and termination of thread executions)

Ii. Thread termination

Several Methods to terminate a thread:

  1. Wait until the thread function runs successfully and automatically ends
  2. Exitthread (), used to end the thread itself
  3. Terminatethread (). All threads can end with this method.
  4. The parent process is closed, and the Child thread is closed.

Only the first method is recommended to end the thread. Other methods have corresponding defects.

The following are some things that happen in the end process:

1. Resources are released in an orderly manner (for example, the C ++ class structure used for resource allocation by the operating system). The Code for thread exit is returned, and the thread kernel object is counted-1.

2. resources related to the operating system are released, but the C ++ class does not analyze the structure, causing memory leakage. Here, if _ beginthreadex is used to create a thread and exitthread or _ endthread is used to release the thread, the thread data block _ tiddata on the heap is not released, causing memory leakage;

3. This function is an asynchronous function that notifies the operating system to return immediately after the end of the thread, regardless of whether the system has actually ended the thread. At the same time, the thread stack will not be released.

4. After you use the exitprogerss and terminateprocess functions to close the process, the process will call terminatethread to close the thread. The effect is as follows: 3. the stack of the thread is not released, and the requested object resources are not released.

1. exitthread ()
VOID ExitThread(  DWORD dwExitCode);

Note:

Header Library
WINBASE. h Coredll. Lib

 

 

Parameters:

Dwexitcode: Specifies the exit code of the thread. You can use getexitcodethread to view the exit code of a thread.

Return Value: None

Note: After the thread ends, the exitcode in the thread kernel object is changed from still_active to the incoming exit code. It corresponds to createthread.

2. terminatethread ()
BOOL TerminateThread(  HANDLE hThread,  DWORD dwExitCode);

Note:

Header Library
WINBASE. h Coredll. Lib

 

 

Parameters:

Hthread: the thread handle to end
Dwexitcode: Specifies the exit code of the thread. You can use getexitcodethread to view the exit code of a thread.

Return Value: 0 indicates failure, and non-0 indicates success;

3. Determine whether the thread is finished
BOOL GetExitCodeThread(  HANDLE hThread,  LPDWORD lpExitCode);
// Determine bool isthreadexit (handle hthread) {bool Bret = false; DWORD dwexitcode; If (getexitcodethread (hthread, & dwexitcode) {If (dwexitcode! = Still_active) Bret = true;} else {// error err = getlasterror (); throw err;} return Bret ;}

Iii. Notes

1. In C ++ multi-threaded programming, try to use _ beginthreadex and _ endthreadex instead of other interfaces.

Reasons for not using _ beginthread:

(1) _ beginthread function parameters are insufficient and some requirements cannot be met,

Reasons for not using _ endthread:

(1) The _ endthread function also has no parameter, that is, the exit code of the thread will be hard encoded as 0;

(2) Before calling exitthread, this function will call closehandle and pass in the handle of the new thread. Code similar to the following may have errors

DWORD dwExitCode;HANDLE hThread = _beginthreadex(...);GetExitCodeThread(hThread, &dwExitCode);CloseHandle(hThread);

Reasons for not using the createthread function:

(1) The Standard C/C ++ Runtime Library was initially not designed for multithreading (the Standard C Runtime Library appeared before the operating system supported the thread ), createthread is an operating system interface. When calling it, the system does not know that it is called by C/C ++. Therefore, to ensure the normal operation of the C/C ++ program, to create a data structure associated with every thread in the runtime database, _ beginthreadex implements this function. In other words, it is extremely insecure to use createthread to create a thread in C/C ++.

Reason for not using the exitthread function:

(1) resources related to the operating system are released, but the class C ++ does not analyze the structure, causing memory leakage. If _ beginthreadex is used to create a thread, when exitthread or _ endthread is used to release a thread, the thread data block _ tiddata on the thread stack is not released, causing memory leakage;

2. What will happen when createthread is used in C/C ++ programming?

When a thread calls a runtime function that requires thread data block _ tiddata, the system first finds the thread data block through local thread storage (TLS, see the following section). If it is null, the C/C ++ Runtime Library calls the thread allocation and initializes a _ tiddata block and associates it with the thread. However, if the signal function of the C/C ++ Runtime library is used, the whole process will be terminated (because the seh of the frame for processing structural exceptions is not ready, rtluserthreadstart will directly call exitprocess to end the process ); in addition, if the thread does not end through _ endthreadex, the thread data block _ tiddata will not be released, resulting in Memory leakage.

Refer:

1. <windows core programming (fifth edition)>

2. About _ beginthreadex, _ beginthread, and createthread

3. MFC multithreading and thread synchronization

4. msdn

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.