-------------------------------------------------- -------------------------------------------------- ------ // Define_mt so what _beginthread () is available # ifndef _mt # define _mt # Endif
#include
1. The character set: The real problem of the software is to resolve, actually how to handle different character sets.
2. Single-byte with double-character character set: ASCII --- DBCS
3.Unicode: Wide Biode Character Set
All characters in the Unicode string are 16 bits (two bytes).
Note: All Unicode functions are starting with WCS, WCS is a wide string English abbreviation. To call the Unicode function, just use the prefix WCS to replace the prefix STR of the ANSI string function.
_Unicode macro is used for C run file Unicode Macro for Windows header When compiling source code modules, it is usually necessary to define both macros.
... is called ANSI and Unicode applications:. Send text string as a character array, not a Chars array or byte array. Use common data types such as TCHAR and PTSTR for text characters and strings. Explicit data types (such as Byte and Pbyte) are used for bytes, byte pointers, and data caches. Use the Text macro for primary characters and strings. Perform a global replacement (for example, replace PSTR in PTSTR) ----- -------------------------------------------------- ---------------------------------
note:
1.C language itself does not input the output statement, the input and output operations are implemented by the library function, such as SCANF and PRINTF. C Implement "functionalization" on the input and output.
2. The length of the label in C language (the number of characters) has no uniform rules, and the system is different. Many systems (IBM PC MS C) take 8 characters. Therefore, it should be understood that the system should be understood as the length of the system to avoid errors and dishes, especially paying with such erroneous compilation, but the results are not aligned or errors.
3. Typical issues:
#include
The result is i = 6 SUM = 9 Because I first merges so that SUM is equal to 9, then carry out self-improved i is equal to 6
If it is sum = ( i) ( i) ( i); result sum = 18, and i = 6, because first is three self-adding 6, then combine equal to 18.
4. Continue and Break
Continue: Skip this loop, followed by the next decision. Break: End the loop, no longer conditional judgment ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------------------------------------- -----------------
Basic arithmetic operator:
5 6-> 11 13.2 17.8-> 21.0
- 18-4-> 14 15.18-21.26 -> - 6.11
* 2 * 3-> 6 2.0 * 3.0-> 6.0
/ 1 / 2-> 0 1.0 / 2.0-> 0.5
% (Surplus) -5% 3 -> - 2 10% 5-> 0
Bit operation:
1. "Brightness and" operator: &
Participate in the two computations of the operation, if the two corresponding bits are 1, the result value of the bit is 1, otherwise 0. Such as:
0 & 0 = 0; 0 & 1 = 0; 1 & 0 = 0; 1 & 1 = 1;
For example: 3 & 5 is not equal to 8, first put 3 and 5 to express the complement, and then press and operate:
3 complement: 00000011 5 complement: 00000101 ------------------ &: 00000001
Therefore, the value of 3 & 5 is 1.
2. "Bit or" operator: |
As long as one is 1 in the two respective positions, the result value of this bit is 1. ie: 0 | 0 = 0; 0 | 1 = 1; 1 | 0 = 1; 1 | 1 = 1;
3. "Different or" operators: ^
The two corresponding positions of the operations are in the same number, and the result is 0 (fake), the heterogeneity is 1 (true)
0 ^ 0 = 0; 0 ^ 1 = 1; 1 ^ 0 = 1; 1 ^ 1 = 0;
4. "Reverse" operator: ~
It is a single operator that is used to reverse a binary number of bits, that is, 0 to 1, will change 1.
5. Left-shift operator: << Used to move all the two inters of a number to the left. A = a << 2; 3 digits left to the left, right, 0. If A = 15, ie: 00 00 11 11, left shift 2 position 00 11 11 00, ie decimal number 60
After the high level, overflow, discarded
6. Right shift operator: >>
Move to the low position of the right end is abandoned, the number of unsigned numbers, the high position is 0.
Note: When the data of different lengths, the system will be aligned in the right end.
Common basic data type description
Type Description Length (byte) Representation
Char characters 1 -128 ~ 127 (-2 seven times to 2 in 7 squares) 1)
Unsigned char None symbolic character type 1 0 ~ 255 (0 ~ 2 seven times) 1)
Signed Char has symbolic characters 1 -128 ~ 127
INT intersection 2 -32768 ~ 32767 (-2 15 times ~ 2 of 15 square minus 1)
Unsigned Int No symbol integer 2 0 ~ 65535 (0 ~ 2) 16 times minus 1)
Signed Int has a symbol integer 2 -32768 ~ 32767
Short Int short integer 2 -32768 ~ 32767
Unsigned short int unsigned short integer 2 0 ~ 65535
Signed short int with short integer 2 -32768 ~ 32767
Long INT long shaping 4 -2 31 square ~ 2 of 31 times minus 1
Signed long int with symbol long mold 4 -2 31 square ~ 2 of 31 times minus 1
Unsigned long int unsigned long molding 4 0 ~ 2 32 times minus 1
FLOAT floating point 4 -3.4 * 10 38 times ~ 3.4 * 10 38 (7 valid numbers) Double double precision type 8-1.7 * 10 308 times to 1.7 * 10 308 (15 A valid number)
Long Double long double precision type 10 -3.4 * 10 4932 times ~ 1.1 * 10 4932 (19 valid numbers) --------------------- -------------------------------------------------- -------------------------------------- Data TypeSthis Topic Lists the data type name used in The Microsoft Foundation Class Library. Most of The Data Types Are EXACTLY The Same As Those in The Windows Software Development Kit (SDK), while Others Aren Unique To MFC.
Commonly Used Windows SDK and MFC Data Types Are As Follows:
Bool a Boolean Value.
BSTR A 32-bit Character Pointer.
Byte an 8-bit integer what not sign.
ColorRef a 32-bit value used as a color value.
DWORD A 32-BIT UNSIGNED INTEGER or the address of a segment and its associated offset.
Long a 32-bit soudned integer.
LPARAM A 32-BIT VALUE Passsed as a parameter to a window process.
LPCSTR A 32-Bit Pointer to a constant character string.
LPSTR A 32-BIT POINTER TO a Character String.
LPCTSTR A 32-BIT POINTER TO A Constant Character String That IS Portable for Unicode and DBCS.
LPTSTR A 32-BIT POINTER TO A Character String That Is Portable for Unicode and DBCS.
LPVOID A 32-BIT POINTER TO An Unspecified Type.
LRESULT A 32-BIT VALUE RETURNED A Window Procedure OR Callback function.
Uint A 16-bit unsigned Integer on Windows Versions 3.0 and 3.1; a 32-bit unsigned integer on Win32.
WNDPROC A 32-BIT POINTER TO A Window Procedure.
Word a 16-bit unsigned integer.
WPARAM A value passed as a parameter to a window procedure or callback function:. 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32 Data types unique to the Microsoft Foundation Class Library include the following: POSITION A value used to denote the position OF AEMENT IN A Collection; Used by MFC Collection Classes.
LPCRECT A 32-BIT POINTER TO a Constant (Nonmodifiable) Rect standure. ----------------------------------- -------------------------------------------------- ----------------------- Short: Short Integer. Word: 16-bit unsigned integer
PBYTE: Pointer to a byte
BYTE: BYTE (8 BITS).
UINT: UNSIGNED INT.
INT: Signed Integer.
Long: 32-bit signed integer
Ulong: unsigned long
Ulonglong: 64-bit unsigned inter
LPVOID: Pointer to Any Type
LPCVOID: Pointer to a constant of any type.
LPCTSTR: An LPCWSTR IF Unicode Is Defined, An LPCSTR OtherWise.
LPCWSTR: PoinTer to a constant null-terminated string of 16-bit uncode character.
LPCSTR: Pointer to a constant Null-Terminated String of 8-bit Windows (ANSI) Characters.
LPTSTR: An LPWSTR IF UNICODE IS Defined, An LPSTR Otherwise
LPWSTR: POINTER TO A NULL-TERMINATED STRING OF 16-Bit Unicode Characters
LPSTR: Pointer to a Null-Terminated String of 8-Bit Windows (ANSI) CHARACTERS
Tchar: for Ansi and DBCS Platforms, Tchar is Defined As Follows: typedef char tchar;
For unicode platforms, tchar is defined as synynymous with the wchar type
Unicode data type
Wchar Wchar 16-Bit Unicode Character Unicode Character
PWSTR points to the pointer to the Unicode string
PCWSTR points to a pointer to a constant Unicode string
_Unicode macro is used for C run file Unicode Macro for Windows header When compiling source code modules, it is usually necessary to define both macros.
============================================================================================================================================================================================================= ============================================================================================================================================================================================================= ======================================= Define constants after constings, the program is You can only read (modify) to prevent this value from being unintentionally modified.
Since the constant is defined, it must be initialized when the constant is defined. Such as:
Const float pi; pi = 3.1415926; // error
Another example: const Int size = 100 * sizeof (int); // ok const Int number = max (15, 23); // Error
In C , constant definitions use const, no #define.
Program memory space
============================================================================================================================================================================================================= ============================================================================================================================================================================================================= =========================================
Code area ............ (Code Area) Global Diversity .............. (Data Area)
Pile area ................ (Heap Area)
Stack area ................ (Stack Area)
A program assigns the operating system to its running memory block to 4 areas:
1. Code area: The code of the program is stored, that is, the various function code blocks in the program.
2. Global Data Area: The global data and static data of the program.
3. Pile area: The dynamic data of the storage program.
4. Stack area: The local data of the program, that is, the data in each function.
============================================================================================================================================================================================================= ============================================================================================================================================================================================================= ==============================================================================================================================================
Common essential characters: / n Enter newline character, cursor movement to the next line, the first line, the return, the cursor moves to the top of the Bank, the top of the Bank (8 is one, the cursor jumps to the next Platage position, such as the 9th or 17th bits, etc.) / B, and the cursor moves to the left mobile one / f Passing page // Used to output a backslash character "/" / 'for output single Quotation marking character "'" / "Used to output a double quotation number character" "" / DDD three-digit number DDD corresponding to ASCII code character / XHH two hexadecimal HH corresponding to ASCII code characters
============================================================================================================================================================================================================= ============================================================================================================================================================================================================= ======================================================================================================= in 32-bit Windows An important feature of the operating system (Windows95 or above and WinNT4.0) is to support an application to perform multiple threads. Users can perform different types of processing in one application.
Differences and connections for processes and threads: A process is a UNDUSTRC. The operating system will create a virtual address space for the process; thread is a Windows object used to run code, and is operating An actuator that is ready to perform.
The process includes code, data, and files, resources such as pipelines, and thread synchronization objects that can be accessed by the thread.
An application can have more than one process, one process can have multiple threads.
Every time Windows creates a new process, you will create a thread for the process to start performing the actual program code, this thread is called the main thread, and a process can only have one main thread. A process can create one or more threads and these threads use the same virtual address space. The address space is provided by the process, which makes it easy to share data between threads, and different threads can execute the same code block, or perform different blocks. When the main thread ends, the entire process is over.
The process has its own virtual address space. When there is more than one thread in a process, each thread share the unified virtual address space, which can obtain system resources for the process and access global variables. Threads can perform any part of the process and create new threads.
An important feature of thread is to create your own process sharing memory, which can access the code and data of the process of calling it. Each thread has its own proprietary stack and proprietary context (proprietary execution context is a small memory, which is used to save the status of the CPU processing register and some data related to the thread execution environment). Generally speaking, the thread does not take up additional memory space.
: Really running program units are threads instead of processes, and process running threads provides the data, resources, and address spaces you want to use.
A main thread can create other threads, and the new thread created can also create other threads to push them at a subkey. All threads of a thread can be performed simultaneously, and the Windows operating system automatically switches between different threads.
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------- Process priority class : Priority Priority Class Priority Description Idle Idle_Priority_Class 4 Free Class Normal Normal_Priority_Class 7-9 Normal Class High High_Priority_Class 13 Advanced class RealTime RealTime_Priority_Class 24 real-time class
--- GetPriorityClass, setPriorityClass: Get, set the priority class for a given process.
DWORD getPriorityClass (Handle HProcess // Process Handle);
Bool SetPriorityClass (Handle HProcess, // Process Handle DWord DWPRIORITYCLASS / Priority);
--- For the current process, you can get your handle through the function getCurrentProcess:
Handle getCurrentProcess (Void); This function return value is the handle of the current process, you can set the priority of the process after the process handle is obtained.
--- Thread priority:
Thread priority flag associated priority tpIdle THREAD_PRIORITY_IDLE -15tpLowest THREAD_PRIORITY_LOWSET -2tpBelowNormal THREAD_PRIORITY_BELOW_NORMAL -1tpNormal THREAD_PRIORITY_NORMAL 0tpAboveNormal THREAD_PRIORITY_ABOVE_NORMAL 1tpHighest THREAD_PRIORITY_HIGHEST 2tpTimeCritical THREAD_PRIORITY_TIME_CRITICAL 15
The overall priority of threads is determined by the priority of the process plus threads. The overall priority value is 1-31.
-------------------------------------------------- -------------------------------------------------- -----------------------
Synchronization through critical regions, mutex, signal lights, events.
Since the operation between the process / thread is parallel, a problem synchronization is generated.
The OS provides a variety of synchronous objects for us to use and can manage the lock and unlock of synchronous objects for us. What we need to do is generating a synchronization object for each resource that needs to be used synchronously. Apply to lock before using the resource, unlock after use. Let's introduce some synchronous objects:
Roundout: The critical area is the simplest synchronization object, which can only be used inside the same process. Its role is to ensure that only one thread can apply to this object, such as the above example, we can use the critical area to perform synchronization processing. Several related API functions are:
Void InitializecriticalSection (lpcritical_section lpcriticalse); generating critical regions
Void deletecriticalsection (lpcritical_section lpcriticalse); delete critical regions
Void EntercriticalSection; Enter the critical area, which is equivalent to the application lock, if the critical zone is being used by other threads, the function will wait for other threads to release BOOL TRYENTERCRITICALSECTION (LPCritical_section lpcriticalsection); enter the critical area, equivalent to application Lock, and EntercriticalSECTION Different if the critical area is being used by other threads, the function will return false immediately, not waiting
Void LeavecriticalSection (lpcritical_section lpcritical); exiting the critical area, equivalent to the application unlock
The following demonstration code demonstrates how to use critical regions to perform data synchronization processing:
// global variable int icounter = 0; critical_section cricounter;
DWORD THREADA (Void * Pd) {INT IID = (int) pd; for (int i = 0; i <8; i ) {EntercriticalSection (& crixnter); int icopy = iCOUNTER; SLEEP (100); icounter = iCopy 1 PRINTF ("Thread% D:% D / N", IID, ICOUNTER); LeaveCriticalSection (& cricounter);} Return 0;} // in main function {// Create a critical area InitializeCriticalSection (& cricounter); // Create thread Handle hThread [3]; CWinThread * pT1 = AfxBeginThread ((AFX_THREADPROC) threadA, (void *) 1); CWinThread * pT2 = AfxBeginThread ((AFX_THREADPROC) threadA, (void *) 2); CWinThread * pT3 = AfxBeginThread ((AFX_THREADPROC) Threada, (void *) 3); hthread [0] = pt1-> m_hthread; hthread [1] = pt2-> m_hthread; hthread [2] = PT3-> m_hthread; // Waiting for thread end // to WaitFormultiplebjects usage It will be said later. WaitFormultipleObjects (3, hthread, true, infinite); // Delete the critical area deletecriticalsection (& cricounter); Printf ("/ NOVER / N");
}
-------------------------------------------------- ------------------------------------ The role of mutual exclusion is very similar to the critical area, but mutual The amount of costume is named, that is, it can use it across the process. So create more resources required for mutual use, so if you only use the critical area to use the critical area to use the critical area to use the critical area to reduce the amount of resources. Because the mutex is to be created, once the mutex of the process is created, it can open it through the name. The following describes an API function on mutex: - The mutex is another grade of naming, and secure kernel object. Its main purpose is to guide access to shared resources. The mutex is a bit like the relay rod of the relay race. To want to "run" thread should wait for the "run" thread to pass the relay stick. Threads with a single access resource create mutual exclusion. All threads who want to access the resource should get a mutex before actually performing operations, and immediately release the mutex immediately, which allows the next wait thread to get a mutex, and then proceed. Create a mutex: Handle CreateMuteX (LPSecurity_Attributes LPMUTEXATTRIBUTES, / / SASTS LPMUTEXATTRIBUTES, / / SAST BOOL BINITIALOWNER, / / The initial state, // If set to true, then the thread that creates it directly has the mutual amount, no need to apply for LPCTSTR LPNAME // Name, can be NULL, but this cannot be opened by other threads / processes); open an existing mutual exclusion: Handle OpenMutex (DWord DwdesiredAccess, // Access mode BOOL BinheritHandle, // Can be Inheriting the LPCTSTR LPNAME // Name); Release the right to use, but the thread that requires calling the function has the right to use the mutual amount of use: BOOL ReleaseMutex (// effect is like the LeavecriticalSection Handle Hmutex // handle); turn off mutually exclusive Quantity: BOOL CloseHandle (Handle Hobject // Handle); Using the right to use the mutex requires the function:
DWORD WAITFORSINGLEOBJECT (Handle Hhandle, // Waiting Object) Wait time, in MS unit, if INFINITE indicates an indefinite waiting); return: Wait_abandoned is in the waiting object to indicate when it is mutually The mutex is turned off, and there is a signal state WAIT_Object_0 gets the right WAIT_TIMEOUT exceeds (dwmilliseconds) specified time
After the thread calls WaitForsingleObject, if the control thread is not allowed to be suspended until the time or the control is obtained.
It is said that we must talk more in depth, there must be a meaning of object (object) in the WaitForsingleObject function. The object here is an object with signal state, and there are two states: there is signal / no signal. The meaning of the waiting is that the waiting object becomes a state of signal, and for mutex, if it is being used, there is no signal state, and it is released to have a signal state. When waiting for success, the waitforSingleObject function sets the mutex without signaling, so that other threads cannot obtain use right and need to continue waiting. The waitforSingleObject function is also queued, ensuring first-to-wait request to first get the right to use
Now let's talk about WaitForsingleObject this function, from the previous example we see that waitforsingleObject This function will wait for an object to become a signal state, then what is the object of the signal state? Below: Mutex Event Semaphore Job Process Thread Waitable Timapole Input Mutex, SMAPHORE, Events (Event) can be used across processes to perform synchronization data operation, while other objects are synchronized with data Not related, but for process and threads, if the processes and threads are not signaling in operation, there is a signal state after exiting. So we can use WaitForsingleObject to wait for the process and thread to exit. (As for the signal light, the usage of events We will follower) We use the waitformultipleObjects function in the previous example, the function of this function is similar to WaitForsingleObject but we can see from the name, WaitFormultiPleObjects will be used to wait for multiple objects to become change There is a signal state, the function prototype is as follows:
DWORD WAITFORMULTIPLEOBJECTS (DWORD NCOUNT, // Waiting Object Quantity const Handle * LPHANDLES, // Object handle array pointer BOOL FWAITALL, // Waiting method, // True means that all objects are waiting to have signal status to return, for false Indicates that any object is changed to have a signal state, returns DWORD dwmilliseconds // timeout setting, in units of ms, if INFINITE indicates an indefinite waiting);
Return value: WAIT_Object_0 to (WAIT_Object_0 Ncount - 1): When Fwaitall is True, all objects become signal state, when fwaitall is false, use the return value to subtract WAIT_Object_0 to get a signal state in an array The subscript. WAIT_ABANDOTONED_0 to (WAIT_ABANED_0 NCOUNT - 1): When Fwaitall is True, all objects become signal state, when fwaitall is false, there is an object in the object to be mutually exclusive, because the mutual exclusion is made The signal state is subtracted to the subscript of the object that changes to a signal state using the return value to obtain the subscript of the object. WAIT_TIMEOUT: indicates that exceeds the specified time. -------------------------------------------------- -------------------------------------------------- ---- Here the signal light has an initial value, indicating how many processes / threads can enter. When the value of the signal light is greater than 0, there is a signal state, and there is no signal state when it is equal to 0, so it can be taken with WaitForsingleObject, when WaitForsingleObject Waiting for success, the value of the signal light will be reduced by 1 until the signal light will increase when it is released. The API functions used for signal lights have the following:
Creating lights: HANDLE CreateSemaphore (LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // security attributes, NULL to use the default security descriptor LONG lInitialCount, // initial value LONG lMaximumCount, // maximum LPCTSTR lpName // name); open lights: HANDLE OpenSemaphore (DWORD dwDesiredAccess , // Access method BOOL BINHERITHANDLE, / / Can be inherited by LPCTSTR LPNAME // Name); Release Signal: BOOL ReleaseSemaphore (Handle HSemaphore, // Release number, let the signal value increase number LPLONG LPPREVIOUSCOUNT / / Used to get the value of the pre-release signal, can be null); shut down signal light: BOOL CloseHandle (Handle Hobject // Handle); Signals Sometimes used as counter, generally set its initial value to 0, first call ReleaseSemaphore To increase its count, then use WaitForsingleObject to reduce its count, unfortunately, we must usually get the current value of the signal light, but can check whether the signal is currently 0 is 0 by setting the wait time of WaitForsingleObject. -------------------------------------------------- -------------------------------------------------- ------- Next, we will tell the last synchronous object: event, the above-mentioned signal light and mutex can ensure that resources are allocated and used, and the event is used to notify other processes / threads. Has been completed.
Event objects can be created in one or two ways, one for automatic reset, waiting for the event object to be used to have a signal after the event object is used, and the event object is automatically changed to no signal state, one for manual reset in other threads The event object status is unchanged after the event object is waited to have a signal using WaitForsingleObject. For example, there are multiple threads waiting for a thread to run, we can use artificial reset events, setting the event to have signal status at the end of the waiting thread, so other multiple threads will be successful (Because the state of the event is not automatically reset). The event-related API is as follows:
Create an event object: Handle CreateEvent (LPSecurity_Attributes LPEventAttributes, // Security Properties, NULL means using the default security description BOOL BMANUALRESET, / / Whether to reset the bool binitialstate, // The initial state is a signal status LPCTSTR LPNAME // Name) Open the event object: Handle OpenEvent (DWORD DWDesiredAccess, // Access mode BOOL BINHERITHANDLE, / / Can be inherited by lpctstr lpname // name); set event is no signal: BOOL Resevent (Handle HEVENT // Handle); Setting There is no signal status: BOOL SETEVENT (Handle HEVENT / / Handle); Close Event Object: BOOL CloseHandle; The following code demonstrates the different effects of automatic reset and manual reset events:
DWORD THREADA (Void * Pd) {INT IID = (int) Pd; // Reopeically open Handle HcOUNTERIN = OPENEVENT (Event_All_Access, False, "SAM SP 44");
Printf ("/ TTHREAD% D BEGIN / N", IID); // is set to have signal state SLEEP (1000); setEvent (hcounterin); Sleep (1000); Printf ("/ TTHREAD% D end / n", IID CLOSEHANDLE (HCOUNTERIN); RETURN 0;}
DWORD THREADB (Void * Pd) {// Waiting for Threada after continuing int IID = (int) pd; // Reopeically restarting handle hcounterin = Openevent (Event_all_Access, false, "SAM SP 44");
IF (Wait_Timeout == WaitForsingleObject (hcounterin, 10 * 1000)) {Printf ("/ TTHREAD% D Wait Time Out / N", IID);} else {printf ("/ t / tTHREAD% D Wait OK / N ", IID);} closehandle (hcounterin); return 0;}
// in main function {handle hcounter = null; if ((hcounter = Openevent) == null) == null) {// If there is no other process to create this event, recreate, the event For artificial reset event hcounter = CreateEvent (NULL, TRUE, FALSE, "SAM SP 44");}
// Create a thread HANDLE hThread [3]; printf ( "test of manual rest event / n"); CWinThread * pT1 = AfxBeginThread ((AFX_THREADPROC) threadA, (void *) 1); CWinThread * pT2 = AfxBeginThread ((AFX_THREADPROC) Threadb, (void *) 2); cwinthread * pt3 = afxbeginthread ((AFX_THREADPROC) Threadb, (void *) 3); hthread [0] = pt1-> m_hthread; hthread [1] = pt2-> m_hthread; hthread [2 ] = pt3-> m_hthread; // Waiting for the thread end WaitFormultiPleObjects (3, hthread, true, infinite); // Close Handle CloseHandle (HCOUNTER); if ((hcounter = Openevent (Event_all_access, false, "SAM SP 44))) == NULL) {// If there is no other process to create this event, recreate it, the event is automatic reset event hcounter = CreateEvent (Null, False, False, "SAM SP 44");} // Create Thread Printf ( "test of auto rest event / n"); pT1 = AfxBeginThread ((AFX_THREADPROC) threadA, (void *) 1); pT2 = AfxBeginThread ((AFX_THREADPROC) threadB, (void *) 2); pT3 = AfxBeginThread ((AFX_THREADPROC) Threadb, (void *) 3); hthread [0] = pt1-> m_hthread; hthread [1] = PT2-> m_hthread; hthread [2] = Pt3-> m_hthread; // Waiting thread end WaitFormultiplebjects (3, hthread, True, Infinite); // Close the handle closehandle (hcounter);
From the execution result, we can see that only one thread in Threada is able to wait for the event object released in Threada during the second execution.
Be careful when processing multi-process / thread synchronous problems, you must avoid death locks, such as now there are two mutual exclusion A and B, two threads TA and TB, they need these two mutuals before execution Delivery, but now this happens, TA has a mutex A, TB has a mutex B, but they are waiting to have another mutual exclusion, this time obvious no one can get my hope H. This kind of resource owned by each other is called a dead lock in the case of waiting for the resources owned by the other party. For more detailed introductions about this problem, please refer to other reference books. -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------! Accurate understanding of the kernel object is crucial for a Windows software developer of.
Kernel objects can be used to manage a wide variety of resources, such as processes, threads, and files.
Access symbol object event object file object file mapping object I / O Complete port object 作 object mailbox object mutually exclusive pipeline object process object beacon Object thread object Wait timer object - kernel object usage count:
The kernel object is owned by the kernel, not by the process. For example, your process calls a function of creating a kernel object, then your process is terminated, then the kernel object is not necessarily revoked. The kernel knows how many processes are using a kernel object because each object contains a count count. It is one of the commonly used data members of all kernel object types.
- Cross-process boundary shared kernel object:. File mapping object: Shared data block between two processes running on the machine, mailbox and specified pipe: send data blocks between the processes running on the connected machine Objects, beacons and events: threads in different processes can synchronize their continuous operation.