Introduction to VC ++ multi-thread programming example (Getting Started)

Source: Internet
Author: User

The multi-thread in VC is widely used and practical. I can see the tutorials on the Internet. I feel that it is quite well written.

I. Question proposal

Compile a time-consuming single-threaded program:

Create an application singlethread Based on the dialog box. In the Main Dialog Box idd_singlethread_dialog, add a button with the ID idc_sleep_six_second and the title "latency of 6 seconds". Add the response function of the button. The Code is as follows:

Void csinglethreaddlg: onsleepsixsecond ()
{
Sleep (6000); // latency 6 seconds
}

Compile and run the application, and click the "latency of 6 seconds" button, you will find that the program is like a "dead" during these 6 seconds, and does not respond to other messages. To better handle this time-consuming operation, we need to learn -- multithreading programming.
Ii. multithreading Overview

Both processes and threads are operating systems. A process is an execution instance of an application. Each process is composed of a private virtual address space, code, data, and other system resources, resources created by a process during running are destroyed upon termination of the process, and the system resources used are released or closed upon termination of the process.
A thread is an execution unit inside a process. After the system has created a process, it actually starts the main execution thread that executes the process. The main execution thread is in the form of a function address, such as the main or winmain function, provide the startup point of the program to the Windows system. The main execution thread is terminated, and the process is terminated accordingly.
Each process has at least one main execution thread, which is automatically created by the system and does not need to be manually created by users. You can create other threads in the application as needed. multiple threads run concurrently in the same process. All threads in a process are in the virtual address space of the process, and these virtual address spaces, global variables, and system resources are used together. Therefore, inter-thread communication is very convenient, multithreading technology is also widely used.
Multi-thread can implement parallel processing, avoiding the CPU time occupied by a task for a long time. Note that most computers are single-processor (CPU) Computers currently. To run all these threads, the Operating System Schedules CPU time for each independent thread, the operating system provides time slices to threads in rotation mode, which gives an illusion that these threads are running simultaneously. It can be seen that two very active threads consume a lot of CPU resources during thread switching in order to seize control of the CPU, but will reduce the system performance. This should be noted in multithreaded programming.
Win32 SDK functions support multi-threaded programming and provide various synchronization, mutex, and critical section operations in the operating system principle. In Visual C ++ 6.0, the use of the MFC class library also achieves multi-threaded programming, making multi-threaded programming more convenient.

Iii. Win32 API support for multi-thread programming

Win32 provides a series of API functions for thread creation, suspension, restoration, termination, and communication. The following describes some important functions.

1. Handle createthread (lpsecurity_attributes lpthreadattributes,
DWORD dwstacksize,
Lpthread_start_routine lpstartaddress,
Lpvoid lpparameter,
DWORD dwcreationflags,
Lpdword lpthreadid );

This function creates a new thread in the process space of the called process and returns the handle of the created thread. The parameters are described as follows:
Lpthreadattributes: pointer to a security_attributes structure. This structure determines the thread Security Attribute and is generally set to null;
Dwstacksize: Specifies the stack depth of the thread, which is generally set to 0;
Lpstartaddress: the address of the function where the new thread starts to execute the time code, that is, the start address of the thread. Generally, it is (lpthread_start_routine) threadfunc, and threadfunc is the name of the thread function;
Lpparameter: Specifies the 32-bit parameter transmitted to the thread during thread execution, that is, the parameter of the thread function;
Dwcreationflags: controls the additional flag created by the thread. Two values can be used. If this parameter is set to 0, the thread starts execution immediately after it is created. If this parameter is create_suincluded, the thread is suspended and not executed immediately after the system generates a thread, until the function resumethread is called;
Lpthreadid: returns the ID of the created thread;
If creation is successful, the thread handle is returned. Otherwise, null is returned.

2. DWORD suspendthread (handle hthread );

This function is used to suspend a specified thread. If the function is successfully executed, the thread execution is terminated. 3. DWORD resumethread (handle hthread );

This function is used to end the suspension status of the thread, the execution thread. 4. Void exitthread (DWORD dwexitcode );

This function is used by the thread to terminate its own execution and is called mainly in the execution function of the thread. The dwexitcode parameter is used to set the exit code of the thread. 5. bool terminatethread (handle hthread, DWORD dwexitcode );

Generally, after the thread finishes running, the thread function returns normally, but the application can call terminatethread to forcibly terminate the execution of a thread. The parameter meanings are as follows:
Hthread: handle of the thread to be terminated;
Dwexitcode: used to specify the exit code of a thread.
It is unsafe to use terminatethread () to terminate the execution of a thread, which may cause system instability. Although the function immediately terminates the execution of the thread, it does not release the resources occupied by the thread. Therefore, this function is generally not recommended.

6. bool postthreadmessage (DWORD idthread,
Uint MSG,
Wparam,
Lparam );

This function puts a message into the message queue of the specified thread, and returns the message before it is processed by the thread.
Idthread: the ID of the thread that receives the message;
MSG: Specifies the message to be sent;
Wparam: Message-related word parameters;
Lparam: long parameters related to messages;
When this function is called, if the thread that is about to receive messages does not create a message loop, the function fails to be executed.

4. Win32 API multi-thread programming routine

Routine 1 multithread1

Create a project multithread1 Based on the dialog box. In the idd_multithread1_dialog dialog box, add two buttons and an edit box. The IDS of the two buttons are idc_start and idc_stop, And the titles are "start ", "Stop": The idc_stop attribute is selected as disabled; the ID of the edit box is idc_time, and the attribute is read-only;

Add the thread function declaration in the multithread1dlg. h file: void threadfunc ();

Note that the declaration of the thread function should be outside the class cmultithread1dlg. Add the protected variable: handle hthread in the cmultithread1dlg class;
DWORD threadid;

The handle and ID of the thread respectively.

Add the global variable m_brun: Volatile bool m_brun to the multithread1dlg. cpp file;

M_brun indicates whether the thread is running.

Note that the global variable m_brun uses the volatile modifier. The volatile modifier tells the compiler not to optimize the variable, that is, it does not need to be put into a register, and the value can be changed externally. Volatile is an important modifier for global variables referenced by multiple threads.

Compile the thread function: void threadfunc ()
{
Ctime time;
Cstring strtime;
M_brun = true;
While (m_brun)
{
Time = ctime: getcurrenttime ();
Strtime = time. Format ("% H: % m: % s ");
: Setdlgitemtext (afxgetmainwnd ()-> m_hwnd, idc_time, strtime );
Sleep (1000 );
}
}

This thread function has no parameters and does not return function values. As long as m_brun is true, the thread is always running.

Double-click the idc_start button to complete the message function void cmultithread1dlg: onstart ()
{
// Todo: add your control notification handler code here
Hthread = createthread (null,
0,
(Lpthread_start_routine) threadfunc,
Null,
0,
& Threadid );
Getdlgitem (idc_start)-> enablewindow (false );
Getdlgitem (idc_stop)-> enablewindow (true );

}

Double-click the idc_stop button to complete the message function void cmultithread1dlg: onstop ()
{
// Todo: add your control notification handler code here
M_brun = false;
Getdlgitem (idc_start)-> enablewindow (true );
Getdlgitem (idc_stop)-> enablewindow (false );
}

Compile and run this routine to realize the multi-thread programming using Win32 API.

Routine 2 multithread2

This thread demonstrates how to transmit an integer parameter to a thread and how to wait for a thread to complete processing.

Create a project multithread2 Based on the dialog box, and add an edit box and a button to the idd_multithread2_dialog dialog box. The IDS are idc_count and idc_start respectively, and the button control title is "start ";
Add the thread function declaration in the multithread2dlg. h file: void threadfunc (INT integer );

Note that the declaration of the thread function should be outside the class cmultithread2dlg.

Add the protected variable: handle hthread in the cmultithread2dlg class;
DWORD threadid;

The handle and ID of the thread respectively.

Open classwizard and add the int variable m_ncount to the idc_count edit box. Add void threadfunc (INT integer) to the multithread2dlg. cpp file)
{
Int I;
For (I = 0; I <integer; I ++)
{
Beep (200,50 );
Sleep (1000 );
}
}

Double-click the idc_start button to complete the message function void cmultithread2dlg: onstart () of this button ()
{
Updatedata (true );
Int integer = m_ncount;
Hthread = createthread (null,
0,
(Lpthread_start_routine) threadfunc,
(Void *) integer,
0,
& Threadid );
Getdlgitem (idc_start)-> enablewindow (false );
Waitforsingleobject (hthread, infinite );
Getdlgitem (idc_start)-> enablewindow (true );
}

By the way, the waitforsingleobject function is prototype: DWORD waitforsingleobject (handle hhandle, DWORD dwmilliseconds );

Hhandle is the handle of the object to be monitored (usually a synchronization object or a thread;
Dwmilliseconds is the timeout value set by the hhandle object, in milliseconds;
When this function is called in a thread, the thread is temporarily suspended. The system monitors the state of the object indicated by hhandle. If the object waiting by the thread changes to a signal state within milliseconds of the suspended dwmilliseconds, the function returns immediately. If the timeout time has reached dwmilliseconds in milliseconds, however, the object indicated by hhandle has not become in a signal state, and the function returns the result. The dwmilliseconds parameter has two special values: 0 and infinite. If the value is 0, the function returns immediately. If the value is infinite, the thread is suspended until the object indicated by hhandle changes to a signal state.
This routine calls this function. After pressing the idc_start button, it waits until the thread returns and restores the idc_start button to its normal state. Compile and run the routine and be careful with it.

Routine 3 multithread3
It is also possible to transmit a struct to a thread function, which can be accomplished by transmitting a pointer parameter pointing to the struct. First define a struct:

Typedef struct
{
Int firstargu,
Long secondargu,
...
} Mytype, * pmytype;

Createthread (null, 0, threadfunc, pmytype,…) when creating a thread ,...);
In the threadfunc function, you can use "force conversion ":

Int intvalue = (pmytype) lpvoid)-> firstargu;
Long longvalue = (pmytype) lpvoid)-> seconddargu;
......

Example 3 multithread3 demonstrates how to transmit a pointer parameter pointing to a struct.

Create a project multithread3 Based on the dialog box. In the idd_multithread3_dialog dialog box, add an edit box idc_millisecond, a button idc_start, the title "start", and a progress bar idc_progress1;
Open classwizard, add the int variable m_nmillisecond to the idc_millisecond edit box, and add the cprogressctrl variable m_ctrlprogress to the idc_progress1 progress bar;
Add a schema definition in the multithread3dlg. h file: struct threadinfo
{
Uint nmillisecond;
Cprogressctrl * pctrlprogress;
};

Thread function declaration: uint threadfunc (lpvoid lpparam );

Note that the two should be outside the cmultithread3dlg class.

Add the protected variable: handle hthread in the cmultithread3dlg class;
DWORD threadid;

The handle and ID of the thread respectively.
In the multithread3dlg. cpp file, perform the following operations:

Defines the public variable threadinfo Info;
Double-click the idc_start button to add the corresponding message processing function void cmultithread3dlg: onstart ()
{
// Todo: add your control notification handler code here

Updatedata (true );
Info. nmillisecond = m_nmillisecond;
Info. pctrlprogress = & m_ctrlprogress;

Hthread = createthread (null,
0,
(Lpthread_start_routine) threadfunc,
& Info,
0,
& Threadid );
/*
Getdlgitem (idc_start)-> enablewindow (false );
Waitforsingleobject (hthread, infinite );
Getdlgitem (idc_start)-> enablewindow (true );
*/
}

Add the statement :{
......

// Todo: add extra initialization here
M_ctrlprogress.setrange (0, 99 );
M_nmillisecond = 10;
Updatedata (false );
Return true; // return true unless you set the focus to a control
}

Add thread processing function: uint threadfunc (lpvoid lpparam ){
Threadinfo * pinfo = (threadinfo *) lpparam;
For (INT I = 0; I <100; I ++)
{
Int ntemp = pinfo-> nmillisecond;

Pinfo-> pctrlprogress-> setpos (I );

Sleep (ntemp );
}
Return 0;
}

By the way, if you add/**/statements to the void cmultithread3dlg: onstart () function, you will find that the progress bar is not refreshed during compilation and running, the main thread also stops responding. Why? This is because the waitforsingleobject function causes a thread deadlock when the sub-thread (threadfunc) ends. Because the waitforsingleobject function will suspend the main thread (no messages can be processed), and the Sub-thread threadfunc is setting a progress bar. The notification event will be detected until the main thread finishes processing the refreshed message. In this way, both threads are waiting for each other, and the deadlock occurs. You should avoid this during programming.
Routine 4 multithread4
This routine tests the maximum number of threads that can be created in windows.

Create a project multithread4 Based on the dialog box. In the idd_multithread4_dialog dialog box, add the idc_test button and the idc_count edit box. The button title is "test" and the edit box attribute is read-only;
In the multithread4dlg. cpp file, perform the following operations:

Add the public variable volatile bool m_brunflag = true;
This variable indicates whether the thread can be created again.

Add a thread function:

DWORD winapi threadfunc (lpvoid threadnum)
{
While (m_brunflag)
{
Sleep (3000 );
}
Return 0;
}

As long as the m_brunflag variable is true, the thread is always running.

Double-click the idc_test button to add the Response Message function void cmultithread4dlg: ontest ()
{
DWORD threadid;
Getdlgitem (idc_test)-> enablewindow (false );
Long ncount = 0;
While (m_brunflag)
{
If (createthread (null, 0, threadfunc, null, 0, & threadid) = NULL)
{
M_brunflag = false;
Break;
}
Else
{
Ncount ++;
}
}
// Create a thread continuously until the thread cannot be created again
M_ncount = ncount;
Updatedata (false );
Sleep (5000 );
// Latency: 5 seconds. Wait until all created threads are finished.
Getdlgitem (idc_test)-> enablewindow (true );
M_brunflag = true;

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.