Windows multithreaded Programming (i)

Source: Internet
Author: User
Tags strtok

Source: http://www.cnblogs.com/TenosDoIt/archive/2013/04/15/3022036.html

CreateThread: Windows API functions (standard form of SDK functions, straightforward creation, can be used in any situation), provides operating system-level creation of threads, and is limited to worker threads

beginthread Beginthreadex: MS Extension SDK function for C Runtime Library, first for the C Runtime library to do some initialization work to ensure that the C Runtime library is working properly, and then call CreateThread to actually create the thread. Beginthread is a functional subset of _beginthreadex, although _beginthread internally calls _beginthreadex but he blocks features such as security features, for example, if you use _beginthread, You cannot create a new thread with a security attribute, you cannot create a paused thread, and you cannot get the ID value of a thread. _beginthread and CreateThread are not the same level, _beginthreadex and createthread are functionally completely replaceable

AfxBeginThread: MFC threads are created by MFC functions that simplify operations or allow threads to respond to messages, can be used for interface threading, or worker threads, but be careful not to use _beginthreadex () or CreateThread in an MFC program ( )。

AfxBeginThread, Beginthread, and Beginthreadex are actually compiler-to-CreateThread encapsulation

How to choose each function when programming

1 MFC Program Selection AfxBeginThread of course, no doubt .

2 If you do not use Microsoft's Visual C + + compiler, your compiler vendor has its own createthred substitution function

3 try not to call CreateThread. Instead, you should use the Visual C + + run-time library function _beginthreadexfor the following reasons:

Consider some of the variables and functions of the standard C run-time library, such as errno, which is a global variable. Global variables for multithreading What will happen, you must know. Therefore, there must be a mechanism for each thread to refer to its own errno variable without touching the errno variable of another thread. _beginthreadex assigns its own tiddata memory structure to each of the threads. This structure preserves the values and addresses of many variables and functions such as errno (see for yourself).
Tiddata is associated with threads through thread-local storage. Specific implementations are available in the threadex.c.
The end thread uses the function _endthreadex function to release the thread's Tiddata data block.
The CRT function library already existed before the thread appeared, so the original CRT could not really support threads, which led us to choose the CRT library when we were programming, and when we consulted the CRT functions in MSDN:
Libraries
LIBC. LIB single thread Static library, retail version
LIBCMT. LIB multithread Static Library, retail version
MSVCRT. LIB Import Library for MSVCRT. DLL, retail version
Such a hint!
Support for threads is a thing of the future!
This also led to many CRT functions in the case of multithreading must have special support, not easy to use CreateThread on OK.
Most CRT functions can be used in the CreateThread thread, to see that only the signal () function is not available, which will cause the process to terminate! But can be used not to say no problem!
Some CRT functions like malloc (), fopen (), _open (), Strtok (), CTime (), or localtime () require specialized thread-locally stored data blocks, which usually need to be established when creating a thread, if using CreateThread, this data block is not built, and then what happens? These functions can still be used in such a thread, and there is no error, in fact the function discovers that the pointer to the block is empty, builds one itself, and then ties it to the thread, which means that if you use CreateThread to create the thread, and then using such a function, There will be a piece of memory unknowingly created, unfortunately, these functions do not delete it, and CreateThread and ExitThread can not know this matter, so there will be memory leak, the thread frequently launched in the software (such as some server software), Sooner or later, the system's memory resources will be exhausted!
_beginthreadex and _endthreadex the memory block, so there's no problem! (no one will intentionally use the CreateThread to create and then terminate with _endthreadex, and the termination of the thread is best not to explicitly call the terminating function, naturally quit the best!) )

If you do something in any thread except the main thread, you should use the multithreaded version of the C Runtime library and use _beginthreadex and _endthreadex:
1 using malloc () and free (), or new and delete
2 Use any function declared in stdio.h or io.h
3 using floating-point variables or floating-point arithmetic functions
4 Call any of the runtime functions that use a static buffer, such as: Asctime (), strtok (), or rand ()

handle's problem , _beginthread's corresponding function _endthread automatically called CloseHandle, and _beginthreadex's corresponding function _endthreadex is not, So CloseHandle anyway is to invoke but _endthread can help you do not have to write, the other two need to write their own! (Jeffrey Richter strongly recommends that as far as possible without the explicit termination function, with the natural exit way, natural exit of course must write their own closehandle)

Reprint from C + + multithreaded instances (_beginthreadex create multithreading)

Two explanations
1) You should never call CreateThread if you are writing a C + + code. Instead, you should use the visualc++ run-time library function _beginthreadex, which should also use _endthreadex. If you do not use the Microsoft Visualc++ compiler, your compiler vendor has its own createthred substitution function. Whatever this alternative function is, you have to use it.

2) because _beginthreadex and _endthreadex are CRT threading functions, you must pay attention to the selection of the compilation options Runtimelibaray, using MT or MTD.

3) The argument list of the _beginthreadex function is the same as the argument list of the CreateThread function, but the parameter names and types are not identical. This is because the development team at Microsoft's C/D + + run-time library believes that the C + + run-time function should not have any dependencies on Windows data types. The _beginthreadex function also returns a handle to the newly created thread, like CreateThread.
Here are some points about _beginthreadex :
&8226; each thread obtains its own tiddata memory structure allocated by the stack of the C + + run-time library. (The TIDDATA structure is located in the visualc++ source code in the Mtdll.h file).

&8226; the address of the thread function passed to _beginthreadex is stored in the Tiddata memory block. The parameters passed to the function are also saved in the data block.

&8226;_beginthreadex does call CreateThread internally, because this is the only way the operating system knows how to create a new thread.

&8226; when Createtthread is called, it is told to start executing a new thread by calling _threadstartex instead of PFNSTARTADDR. Also, the arguments passed to the thread function are tiddata structures rather than pvparam addresses.

&8226; If all goes well, it will return the thread handle like CreateThread. If any operation fails, it returns NULL.

4) Some key points of _endthreadex:
&8226; The _GETPTD function of the C run-time library invokes the operating system's TlsGetValue function, which is responsible for retrieving the address of the Tiddata memory block of the calling thread.

&8226; then the data block is freed, and the ExitThread function of the operating system is called so that the thread is actually undone. Of course, the exit code is set and passed correctly.

5) Although the simplified version of the _beginthread and _endthread are also provided, but the control is too poor, so generally not used.

6) thread handle because it is a kernel object, it needs to be closehandle at the end.

7) More APIs:

HANDLE getcurrentprocess ();

HANDLE GetCurrentThread ();

DWORD GetCurrentProcessId ();

DWORD GetCurrentThreadID ().

DWORD setthreadidealprocessor (HANDLE hthread,dword dwidealprocessor);

BOOL setthreadpriority (HANDLE hthread,int npriority);

BOOL Setpriorityclass (GetCurrentProcess (), idle_priority_class);

BOOL GetThreadContext (HANDLE hthread,pcontext PCONTEXT); BOOL SwitchToThread ();
Three notes
1) The termination of the main thread of C + + also terminates all the child threads created by the main thread, regardless of whether the child thread has completed execution. So if WaitForSingleObject is not called in the code above, the 2 child threads T1 and T2 may not be executed or executed at all.
2) If a thread hangs and then has a call to WaitForSingleObject to wait for the thread, it causes a deadlock. So the above code will deadlock if it does not call ResumeThread.

Why use the _beginthreadex of the C run-time library instead of the createthread of the operating system to create threads?

From July 1999 MSJ Magazine's "Win32 q&a" column

You might say I've been using CreateThread to create threads, always working well, why use _beginthreadex instead of CreateThread, let me tell you why.
There are two ways to answer a question, one is simple and the other is complex.
If you don't want to look at the following lengthy speech, I can tell you the simple answer: _beginthreadex calls CreateThread internally, and _beginthreadex does a lot of work before calling, making it safer than createthread.

_beginthreadex usage

Header file: process.h

function Prototypes: unsigned long _beginthreadex (void *security, unsigned stack_size, Unsigned (__stdcall *start_address ) (void *), void *arglist, unsigned INI Tflag, unsigned *thrdaddr );

1th parameter: Security property, NULL is the default security attribute
2nd parameter: Specifies the size of the thread stack. If 0, the thread stack size is the same as the thread that created it. General use 0
The 3rd parameter: Specify the address of the thread function, that is, the function address that the thread calls to execute (with the function name, the function name represents the address, note that the function access must be __stdcall, the function return value must be unsigned, the function parameter must be void*)
The 4th parameter: A pointer to a parameter passed to the thread, which can then be converted into a pointer to the corresponding class by passing in a pointer to the object.
5th parameter: Thread initial state, 0: Run immediately; Create_suspend: Hang (if the condition is defined as hanging, call ResumeThread (HANDLE) to activate the thread's run)
6th parameter: The address used to record the thread ID

Examples of Use

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 66676869707172737475767778798081828384858687 #include<string> #include<iostream> #include<process.h> #include<windows.h> usingnamespacestd; structArg//用来传参给线程函数{    doubled_;    string str_;    Arg(doubledd, string ss):d_(dd), str_(ss){}};//线程绑定的函数返回值和参数是确定的,而且一定要__stdcallunsigned __stdcall threadFun(void*){    for(inti = 0; i < 10; i++)        cout<<i<<endl;    return1;} //可以通过结构体来传入参数unsigned __stdcall threadFunArg(void*arglist){    Arg *p = (Arg *)arglist;    cout<<p->d_<<endl;    cout<<p->str_<<endl;    return2;} //简单的线程类classThreadClass{private:    string str_;    inti_;public:    ThreadClass(string s, int i):str_(s), i_(i){}    staticunsigned __stdcall threadStaic(void*arg)    {        ThreadClass *p = (ThreadClass *)arg;        p->threadfun();        return 3;    }    voidthreadfun()    {        cout<<str_<<endl;        cout<<i_<<endl;    }}; intmain(){    unsigned intthID1, thID2, thID3, thID4;    HANDLEhth1, hth2, hth3, hth4;    Arg arg(3.14, "hello world");    ThreadClass tclass("welcom", 999);    //注意的是_beginthreadex是立即返回的,系统不会等线程函数执行完毕,因此要保证    //局部arg变量 在线程函数执行完毕前不会释放,更安全的是使用new来构造arg    hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, NULL, 0, &thID1);    hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, NULL, 0, &thID2);    hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunArg, &arg, 0, &thID3);    hth4 = (HANDLE)_beginthreadex(NULL, 0, ThreadClass::threadStaic, &tclass, 0,                                   &thID4);     //主线程一定要等待子线程结束    WaitForSingleObject(hth1, INFINITE);    WaitForSingleObject(hth2, INFINITE);    WaitForSingleObject(hth3, INFINITE);    WaitForSingleObject(hth4, INFINITE);    DWORDexitCode1, exitCode2, exitCode3, exitCode4;    GetExitCodeThread(hth1, &exitCode1);    GetExitCodeThread(hth2, &exitCode2);    GetExitCodeThread(hth3, &exitCode3);    GetExitCodeThread(hth4, &exitCode4);    cout<<endl<<"exitcode::"<<exitCode1<<" "<<exitCode2<<" "<<exitCode3<<" "        <<exitCode4<<endl;    cout<<"ID:"<<thID1<<" "<<thID2<<" "<<thID3<<" "<<thID4<<endl;     //一定要记得关闭线程句柄    CloseHandle(hth1);    CloseHandle(hth2);    CloseHandle(hth3);    CloseHandle(hth4);}

Windows multithreaded Programming (i) (GO)

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.