VC ++ notes -- multitasking, processes, and threads in the MFC Environment

Source: Internet
Author: User

12.1.1 collaborative multitasking for Windows 3.x

In a 16-bit Windows 3. X, the application has control over the CPU. Only after getmessage, peekmessage, waitmessage, or yield is called can the program control the CPU to the system, and the system transfers the control to other applications. If the application cannot call one of the above four functions for a long time, the program will always exclusively occupy the CPU, and the system will be suspended and the user input will not be accepted.

Therefore, when designing a 16-bit application, the programmer must properly design the message processing function so that the program can return to the message loop as soon as possible. If the program requires time-consuming operations, ensure that the program periodically calls one of the above four functions during the operation.

In Windows 3. in environment X, you need to design a backend that can perform real-time operations (such as real-time monitoring and read/write of communication ports ), in addition, it is almost impossible for all interfaces to respond to separate applications entered by users.

Someone may think of using the cwinapp: onidle function to execute background work, because this function is called when the main message loop of the program is idle. However, onidle execution is not reliable. For example, if you open a menu or modal dialog box in the program, onidle stops calling because the program cannot return to the main message loop! The same problem occurs when calling peekmessage in the real-time task code. Unless the program ensures that the user does not select a menu or the modal dialog box is displayed, the program cannot return to the call of peekmessage, this will cause real-time processing interruption in the background.

The compromise is that a non-modal dialog box is displayed during long-term work and the main window is disabled. backend operations are performed in batches in the message loop. The dialog box displays the progress of the job, or contains a Cancel button to give the user a chance to interrupt a long-term job. The typical code is shown in listing 12.1. This not only ensures real-time work, but also enables the program to respond to user input in a limited manner. However, at this time, the program can no longer do anything else for the user.

Listing 12.1 A Way To prevent programs from being suspended in a collaborative multi-task environment

Babort = false;

Lpmydlgproc = makeprocinstance (mydlgproc, hinst );

Hmydlg = createdialog (hinst, "abort", hwnd, lpmydlgproc); // create a non-Modal Dialog Box

Showwindow (hmydlg, sw_normal );

Updatewindow (hmydlg );

Enablewindow (hwnd, false); // disable the Main Window

...

While (! Babort)

{

...// Perform a background operation

...

While (peekmessage (& MSG, null, pm_remove ))

{

If (! Isdialogmessage (hmydlg, & MSG ))

{

Translatemessage (& MSG );

Dispatchmessage (& MSG );

}

}

}

Enablewindow (hwnd, true); // allows the Main Window

Destroywindow (hmydlg );

Freeprocinstance (lpmydlgproc );

 

12.1.2 preemptive multitasking in Windows 95/NT

In a 32-bit Windows system, preemptive multitasking is used, which means that the CPU usage time of the program is determined by the system. The system allocates a certain amount of CPU time for each program. When the program runs beyond the specified time, the system will interrupt the program and transfer the CPU control to other programs. Unlike collaborative multitasking, such interruptions are in the assembly language level. The program does not have to call a function like peekmessage to give up control of the CPU, so it can perform time-consuming work without causing system suspension.

For example, in Windows 3.x, if an application is in an endless loop, the entire system will be paralyzed. The only solution is to restart the machine. In Windows 95/NT, the crash of a program generally does not cause a crash, and other programs can still run, you can press CTRL + ALT + DEL to open the task list and close programs with no response.

12.1.3 process and thread

In a 32-bit Windows system, the term multitasking means that the system can run multiple processes at the same time, and each process can run multiple threads at the same time.

A process is a running instance of an application. Each process has its own private virtual address space. Each process has a main thread, but another thread can be created. Threads in a process are executed in parallel. The CPU usage time of each thread is divided by the system.

The thread can be considered as the basic entity for the CPU time allocated by the operating system. The system constantly switches between threads. the interruption to threads is at the assembly language level. The system allocates a CPU time slice to each thread. A thread has control over the CPU only within the allocated time slice. In fact, in a PC, only one thread is running at a time. Because the system divides the time slice for each thread very small (about 20 ms), it seems that multiple threads are running at the same time.

All threads in the process share the virtual address space of the process, which means that all threads can access the global variables and resources of the process. This aspect brings convenience to programming, but it is also prone to conflicts.

Although the time-consuming work in the process will not cause the system to be suspended, this will cause the process to be suspended. Therefore, if a process requires both long-term work and user input, it can start a thread to take charge of time-consuming work, and the main thread can still interact with the user.

12.1.4 thread creation and Termination

Threads are divided into user interface threads and worker threads. The User Interface thread has its own message pump to process interface messages and can interact with users. The worker thread does not have a message pump and is generally used to complete background work.

The thread of the MFC application is represented by the object cwinthread. In most cases, the program does not need to create a cwinthread object by itself. A cwinthread object is automatically created when the afxbeginthread function is called.

For example, the Code in listing 12.2 demonstrates the creation of a worker thread. The afxbeginthread function is used to create a new thread. The first parameter is the address of the function representing the thread. In this example, It is mythreadproc. The second parameter is the parameter passed to the thread function. It is assumed that the cmyobject object is used by the thread, so the pnewobject pointer is passed to the new thread. The thread function mythreadproc is used to execute threads. Pay attention to the declaration of this function. A thread function has a 32-bit pparam parameter to receive necessary parameters.

Create a worker thread in listing 12.2

// Main thread

Pnewobject = new cmyobject;

Afxbeginthread (mythreadproc, pnewobject );

 

// New thread

Uint mythreadproc (lpvoid pparam)

{

Cmyobject * pobject = (cmyobject *) pparam;

 

If (pobject = NULL |

! Pobject-> iskindof (runtime_class (cmyobject )))

Return-1; // invalid Parameter

 

// Use a pobject object to complete a job

 

Return 0; // The thread ends normally.

}

 

 

The afxbeginthread statement is:

Cwinthread * afxbeginthread (afx_threadproc pfnthreadproc, lpvoid pparam, int npriority = thread_priority_normal, uint nstacksize = 0, DWORD dwcreateflags = 0, define lpsecurityattrs = NULL );

 

The pfnthreadproc parameter is the address of the working thread function. Pparam is the parameter passed to the thread function. Npriority is the thread priority, which is generally thread_priority_normal. If it is 0, the priority of the thread to be created is used. Nstacksize indicates the stack size of the thread. If it is 0, the stack size is the same as that of the Creation thread. Dwcreateflags specifies the initial state of the thread. If it is 0, the thread is executed immediately after creation. If it is create_suincluded, the thread is suspended after creation. The lpsecurityattrs parameter is used to describe the confidentiality attribute, which is generally 0. The function returns the pointer to the newly created cwinthread object.

The program should save the cwinthread pointer returned by afxbeginthread to control the created thread. For example, you can call cwinthread: setthreadpriority to set the thread priority and use cwinthread: suspendthread to suspend the thread. If the thread is suspended, the thread does not run until cwinthread: resumethread is called.

To create a user interface thread, a new class must be derived from cwinthread. In fact, the cwinapp class that represents the main thread of the process is the derived class of cwinthread. The derived classes must be declared and implemented using the declare_dyncreate and implement_dyncreate macros. You need to override the initinstance, exitinstance, run, and other functions of the derived class.

You can use another version of the afxbeginthread function to create a user interface thread. Function declaration:

Cwinthread * afxbeginthread (cruntimeclass * pthreadclass, int npriority = thread_priority_normal, uint nstacksize = 0, DWORD dwcreateflags = 0, lpsecurity_attributes securlpityattrs = NULL );

The pthreadclass parameter points to a cruntimeclass object, which is created from the derived class of cwinthread using the runtime_class macro. The returned values of other parameters and functions are the same as those of afxbeginthread In the first version.

When one of the following events occurs, the thread is terminated:

The thread calls exitthread.

The thread function returns, that is, the thread implicitly calls exitthread.

Exitprocess is displayed or implicitly called by any thread of the process.

Use the thread handle to call terminatethread.

Use a process handle to call terminateprocess.

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.