VC multithreaded Programming detailed _c language

Source: Internet
Author: User
Tags function prototype mutex semaphore terminates thread class

This article describes the VC multithreaded programming concepts and skills, to share with you for your reference. The specific analysis is as follows:

First, multithreading programming essentials

A thread is an execution path of a process that contains separate stacks and CPU register states, and each thread shares all of the process resources, including open files, signal identities, and dynamically allocated memory. All threads within a process use the same address space, and the execution of those threads is controlled by the system scheduler, which determines which thread executes and when the thread is executed. A thread has a priority, and a thread with a lower priority must wait until a higher-priority thread finishes execution. On multiprocessor machines, the scheduler can put multiple threads on a different processor to run, which balances the processor's tasks and improves the system's operational efficiency.

Windows is a multitasking operating system that contains one or more threads within a process in Windows. The Win32 API in the 32-bit Windows environment provides the interface functions required for multi-threaded application development, and the standard C libraries provided in VC can also develop multi-threaded applications, and the corresponding MFC class libraries encapsulate multithreaded programming classes, The user can choose the appropriate tool according to the needs and characteristics of the application at development time. In order to get a complete understanding of Windows multithreaded programming technology, this article will focus on the WIN32 API and MFC two ways to develop multithreaded programs.

Multithreaded programming in the WIN32 mode and MFC class Library support the principle is consistent, the main thread of the process in any need to create a new thread. Automatically terminates the thread when the thread has finished executing; When the process is finished, all threads are terminated. All active threads share the resources of the process, so you need to consider the issue of conflict when multiple threads access the same resource at programming time. When a thread is accessing a process object, and another thread is changing the object, it may produce an erroneous result that can be resolved programmatically.

Second, multithreaded programming under the Win32 API

The Win32 API is the interface between the Windows operating system kernel and the application, which functions to package the functions provided by the kernel, and the application obtains the corresponding system functions by invoking the related functions. To provide multi-threaded functionality to applications, the WIN32 API function set provides a collection of functions that handle multithreaded programs. Programming directly with the WIN32 API has many advantages: Win32 based application code is small and highly efficient, but it requires programmers to write more code and to manage the resources that all systems provide to the program. Using the Win32 API to write programs directly requires programmers to have a certain understanding of the Windows system kernel, will occupy programmers a lot of time to manage the system resources, so the programmer's efficiency is reduced.

1. Create and terminate threads with the WIN32 function

The WIN32 function library provides functions that manipulate multithreading, including creating threads, terminating threads, establishing mutexes, and so on. A function that creates a new thread in the main thread of the application or in another active thread is as follows:

Copy Code code as follows:
HANDLE CreateThread (lpsecurity_attributes lpthreadattributes,dword dwstacksize,lpthread_start_routine Lpstartaddress,lpvoid Lpparameter,dword Dwcreationflags,lpdword Lpthreadid);

Returns the handle of the thread if the creation succeeds, otherwise null is returned. When a new thread is created, the thread starts execution. However, if the create_suspended feature is used in dwCreationFlags, the thread does not execute immediately, but instead suspends the start thread until the ResumeThread is invoked, in which case the following function can be invoked to set the thread's precedence:

Copy Code code as follows:
BOOL setthreadpriority (HANDLE hthread,int npriority);

When the function of the calling thread returns, the thread terminates automatically. Call a function if you want to terminate the thread during execution:

Copy Code code as follows:
VOID ExitThread (DWORD dwexitcode);

If you terminate a thread outside of a thread, you can call the following function:

Copy Code code as follows:
BOOL TerminateThread (HANDLE hthread,dword dwexitcode);

Note, however, that this function can cause system instability and that the resources occupied by the thread are not freed. Therefore, it is not recommended to use this function in general.

If the thread to terminate is the last thread in the process, the corresponding process should terminate after the thread is terminated.

2. Synchronization of Threads

In a thread body, if the thread is completely independent and does not conflict with resource operations such as data access by other threads, it can be programmed in a usually single-threaded way. However, this is often not the case in multithreading, where some resources are often accessed concurrently between threads. The Win32 API provides a variety of synchronization control objects to help programmers resolve shared resource access conflicts, in order to resolve this thread synchronization problem, because it is unavoidable that access to shared resources can cause conflicts. Let's introduce the wait function before introducing these synchronization objects, because this function is used for all control object access control.

The Win32 API provides a set of wait functions that enable a thread to block its own execution. These functions generate a signal in one or more of the synchronization objects in their arguments, or they are returned only after the specified wait time. When the wait function is not returned, the thread is in a waiting state, at which point the thread consumes only a small amount of CPU time. Using the wait function can not only ensure the synchronization of the thread, but also improve the running efficiency of the program. The most commonly used wait functions are:

Copy Code code as follows:
DWORD WaitForSingleObject (HANDLE hhandle,dword dwmilliseconds);

The function Waitformultipleobject can be used to simultaneously monitor multiple synchronization objects, which are declared as:

Copy Code code as follows:
DWORD Waitformultipleobject (DWORD ncount,const HANDLE *lphandles,bool Bwaitall,dword dwmilliseconds);

(1) Mutex object

A mutex object's state is signaled when it is not owned by any thread, and is not signaled when it is owned. Mutex objects are ideal for reconciling multiple threads with mutually exclusive access to shared resources. You can use this object in the following steps:

First, create the mutex object and get the handle:

Copy Code code as follows:
HANDLE CreateMutex ();

Then, the thread may produce a conflict before the zone (that is, before accessing the shared resource) calls WaitForSingleObject, passes the handle to the function, and requests the mutex object:

Copy Code code as follows:
Dwwaitresult = WaitForSingleObject (hmutex,5000l);

End of shared resource access frees up the use of mutex objects:

Copy Code code as follows:
ReleaseMutex (Hmutex);

The mutex object can only be occupied by one thread at a time, and when the mutex object is occupied by a thread, it must wait for the first thread to be released before it can succeed.

(2) Signal object

Signal objects allow simultaneous access to multiple threads to share resources, specifying the maximum number of simultaneous threads to be accessed when creating an object. When a thread requests access success, the counter in the signal object is reduced by one, and after the call to the ReleaseSemaphore function, the counter in the signal object plus one. Where the counter value is greater than or equal to 0, but is less than or equal to the maximum value specified at creation time. If an application sets the initial value of its counter to 0 when it creates a semaphore object, it blocks other threads and protects the resource. When initialization is complete, calling the ReleaseSemaphore function to increase its counter to the maximum, normal access is available. You can use this object in the following steps:

First, create the signal object:

Copy Code code as follows:
HANDLE CreateSemaphore ();

or open a Signal object:

Copy Code code as follows:
HANDLE OpenSemaphore ();

The WaitForSingleObject is then invoked before the thread accesses the shared resource.

After the shared resource access is complete, the use of the semaphore object should be released:

Copy Code code as follows:
ReleaseSemaphore ();

(3) Event object

An event object is the simplest synchronization object that includes both a signal and a signal-free state. When a thread accesses a resource, it needs to wait for an event to occur, and the event object is most appropriate. For example, the monitoring thread is activated only after the communication port buffer has received data.

Event objects are created using the CreateEvent function. The function can specify the initial state of the class and event of the event object. If the event is manually reset, it will always remain signaled until the ResetEvent function is reset to a signal-less event. If an event is automatically reset, its state automatically becomes signaled when a single waiting thread is released. Use SetEvent to set the event object to a signaled state. When you create an event, you can name the object so that threads in other processes can open the event object handle of the specified name with the OpenEvent function.

(4) Exclusion zone Object

When executed asynchronously in the exclusion zone, it can only share resource processing between threads in the same process. Although several of the methods described above are available, the method that uses the exclusion zone makes synchronization management more efficient.

When used, a critical_section object is defined, and the following function is called to initialize the object before the process is used:

Copy Code code as follows:
VOID initializecriticalsection (lpcritical_section);

When a thread uses the exclusion zone, call the function: EnterCriticalSection or tryentercriticalsection;

When required to occupy, exit the exclusion zone, call function LeaveCriticalSection, release the exclusion of the object's occupation, for other threads to use.

Three, based on MFC multithreaded programming

MFC is Microsoft's VC development integration Environment provided to the programmer's basic function library, it uses the way of class library to encapsulate the Win32 API, in class way to provide to developers. Because of its fast, simple, powerful features such as the broad masses of developers love. Therefore, it is recommended that you use the MFC class library for application development.

VC + + included in the MFC class library, providing support for multithreaded programming, the basic principle and based on the Win32 API design consistent, but because MFC to synchronize objects to do encapsulation, so realize more convenient, avoid the object handle management cumbersome work.

In MFC, threads fall into two categories: worker threads and user interface threads. The worker thread is consistent with the thread described earlier, and the user interface thread is a thread that can receive user input, process events, and messages.

1. Worker Threads

The work-thread programming is simpler, the design idea is basically consistent with the previous one: A basic function represents a thread, after creating and starting a thread, the thread enters the running state; If a thread uses a shared resource, it needs to be synchronized with the resource. This way you can invoke a function when you create a thread and start a thread:

Copy Code code as follows:
Cwinthread*afxbeginthread (
Afx_threadproc Pfnthreadproc,
LPVOID Pparam,
int npriority= Thread_priority_normal,
UINT nstacksize = 0,
DWORD Dwcreateflags=0,
Lpsecurity_attributes lpsecurityattrs = NULL);

The parameter pfnthreadproc is the thread execution body function, the function prototype is: UINT threadfunction (LPVOID pparam).

Parameter pparam is a parameter passed to the execution function;

Parameter npriority is the thread execution permission, optional value:

Thread_priority_normal, Thread_priority_lowest, Thread_priority_highest, Thread_priority_idle.

The parameter dwcreateflags is a flag that is created by the thread, create_suspended, indicating that the thread was created in a pending state, the thread continues to run after the ResumeThread function is invoked, or that the value "0" indicates that the thread was created and running.

The return value is the CWinThread class object pointer, its member variable m_hthread as a thread handle, and the function parameters of the thread operation in the Win32 API mode require that the thread handle be supplied, so that when the thread is created, all the Win32 API functions can be used on the pwinthread- >m_thread threads to perform related operations.

Note: If you create and start a thread in a class object, you should define the thread function as a global function outside of the class.

2. User interface thread

An MFC-based application has an Application object that is an object of the CWinApp derived class that represents the main thread of the application process. When the thread finishes and exits the thread, the process automatically ends because no other threads exist in the process. Class CWinApp is derived from CWinThread, and CWinThread is the base class for user interface threads. When we write user interface threads, we need to derive our own thread classes from CWinThread, ClassWizard can help us to do this work.

First derive a new class with ClassWizard and set the base class to CWinThread. Note: The Declare_dyncreate and implement_dyncreate macros of the class are required because the object of the class needs to be created dynamically when the thread is created. Depending on your needs, you can place the initialization and end code in the InitInstance and ExitInstance functions of the class, respectively. If you need to create a window, you can do so in the InitInstance function. Then create the thread and start the thread. There are two ways to create a user interface thread, and MFC provides two versions of the AfxBeginThread function, one for creating user interface threads. The second method consists of two steps: First, the calling thread class's constructor creates a thread object, and secondly, calls the CWinThread::CreateThread function to create the thread. After the thread is set up and started, it is always valid during the execution of the threads function. If it is a thread object, the thread ends before the object is deleted. CWinThread has done the thread end work for us.

3. Thread synchronization

We introduced the Win32 API provides several objects related to thread synchronization, in the MFC class library for these objects are class encapsulation, they have a common base class CSyncObject, their corresponding relationship is: semaphore corresponding CSemaphore, The mutex corresponds to the CMutex, the event correspondence CEvent, the criticalsection corresponds ccriticalsection. In addition, MFC also encapsulates two wait functions, namely CSingleLock and CMultiLock. Because the four object usages are similar, here is an example of CMutex:

Create a CMutex object:

Copy Code code as follows:
CMutex Mutex (false,null,null);

Or

Copy Code code as follows:
CMutex Mutex;

Use the following code when each thread wants to access a shared resource:

Copy Code code as follows:
CSingleLock SL (&mutex);

Sl. Lock ();

if (SL. IsLocked ())

Operating on shared resources ...

Sl. Unlock ();

Iv. concluding remarks

If the user's application requires multiple tasks to be processed at the same time, multithreading is an ideal choice. Here, note that in multithreaded programming, you should be particularly careful with resource sharing issues and multithreaded debugging issues.

I hope this article on the VC program for everyone to help.

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.