Multi-thread programming 2-multi-thread development in MFC

Source: Internet
Author: User
Tags export class protected constructor

Download source code

V. multi-thread programming supported by MFC

There are two types of threads in MFC, namely the worker thread and the user interface thread. The main difference between the two is that the worker thread does not have a message loop, and the user interface thread has its own message queue and message loop.
The worker thread does not have a message mechanism and is usually used to execute background computing and maintenance tasks, such as lengthy computing processes and printer background printing. User Interface threads are generally used to process user input independent of other threads, and respond to events and messages generated by users and systems. However, for Win32 API programming, there is no difference between the two threads. They only need the thread startup address to start the thread to execute the task.
In MFC, the global function afxbeginthread () is generally used to create and initialize the running of a thread. This function has two reload forms for creating a worker thread and a user interface thread respectively. The prototype and parameters of the two overloaded functions are described as follows:

 
(1) cwinthread * afxbeginthread (afx_threadproc pfnthreadproc, lpvoid pparam, npriority = Priority, uint nstacksize = 0, DWORD dwcreateflags = 0, lpsecurity_attributes lpsecurityattrs = NULL );

Pfnthreadproc: pointer to the execution function of the worker thread. The prototype of the thread function must be declared as follows:

 
Uint executingfunction (lpvoid pparam );

Please note that executingfunction () should return a uint type value to indicate the reason for the function to end. Generally, if 0 is returned, the execution is successful.

    • Pparam: A 32-bit parameter passed to the thread function. The execution function will explain the value in some way. It can be a value, a pointer to a structure, or even ignored;
    • Npriority: the priority of the thread. If the value is 0, the thread has the same priority as its parent thread;
    • Nstacksize: the size of the stack allocated by the thread, in bytes. If nstacksize is set to 0, the thread stack is set to the same size as the parent thread stack;
    • Dwcreateflags: If it is 0, the thread starts execution immediately after creation. If it is create_suspend, the thread is suspended immediately after creation;
    • Lpsecurityattrs: Specifies the thread's Security Attribute pointer, which is generally null;
 
(2) cwinthread * afxbeginthread (cruntimeclass * pthreadclass, int npriority = thread_priority_normal, uint nstacksize = 0, DWORD dwcreateflags = 0, lpsecurity_attributes lpsecurityattrs = NULL );

Pthreadclass is a pointer to the runtime Class Object of an export class of cwinthread, which defines the startup and exit of the created user interface thread; the meaning of other parameters is the same as that of Form 1. The thread generated using the prototype of the function also has a message mechanism. In future examples, we will find that the mechanism is almost the same as that of the main thread.

The following describes the data members and common functions of the cwinthread class.

    • M_hthread: handle of the current thread;
    • M_nthreadid: ID of the current thread;
    • M_pmainwnd: Point to ApplicationProgramPointer to the Main Window
 
Bool cwinthread: createthread (DWORD dwcreateflags = 0, uint nstacksize = 0, lpsecurity_attributes lpsecurityattrs = NULL );

The dwcreateflags, nstacksize, and lpsecurityattrs parameters in this function have the same meaning as the corresponding parameters in the API function createthread. If the function is successfully executed, a non-0 value is returned; otherwise, 0 is returned.
Generally, afxbeginthread () is called to create and start a thread at a time, but a two-step method can also be used to create a thread: first, create an object of the cwinthread class, then, call the createthread () member function of the object to start the thread.

 
Virtual bool cwinthread: initinstance ();

Reload this function to control the initialization of the user interface thread instance. If Initialization is successful, a non-0 value is returned; otherwise, 0 is returned. The User Interface thread often reloads this function. The worker thread generally does not use initinstance ().

 
Virtual int cwinthread: exitinstance ();

Reload the function before the end of the thread to perform some necessary cleaning. This function returns the exit code of the thread. 0 indicates that the execution is successful, and a non-0 value indicates various errors. Like the initinstance () member function, this function is only applicable to user interface threads.

6. multi-threaded MFC programming example

In the Visual C ++ 6.0 programming environment, we can either write a C-style 32-bit Win32 application or use the MFC class library to write a C ++-style application, both have their own advantages and disadvantages. Win32-based application executionCodeSmall, efficient, but requires programmers to write a lot of code, and needs to manage all the resources provided by the system to the program; and the application based on the MFC class library can quickly establish an application, the Class Library provides a large number of encapsulation classes for programmers, and developer Studio provides some tools for programmers to manage user source programs. Its disadvantage is that the class library code is huge. Because of the fast, simple, and powerful advantages of using the class library, unless you have special needs, we recommend that you use the MFC class library for program development in Visual C ++.

We know that there are two types of threads in MFC: User Interface thread and worker thread. We will give examples respectively.

Use the MFC class library Programming to Implement the worker thread

Routine 5 multithread5

To compare with Win32 API, we use the MFC class library Programming to Implement the routine 3 multithread3.

  1. Create a project multithread5 Based on the dialog box. In the idd_multithread5_dialog dialog box, add an edit box idc_millisecond, a button idc_start, the title "start", and a progress bar idc_progress1;
  2. 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;
  3. Add a schema definition in the multithread5dlg. h file:
    Struct threadinfo {uint nmillisecond; cprogressctrl * pctrlprogress ;};

    Declaration of thread functions:

    Uint threadfunc (lpvoid lpparam );

    Note that the two should be outside the cmultithread5dlg class.

    Add the protected variable to the cmultithread5dlg class:

    Cwinthread * pthread;
  4. In the multithread5dlg. cpp file, perform the following operations: define public variables:
    Threadinfo Info;

    Double-click the idc_start button to add the corresponding message processing function:

    Void cmultithread5dlg: onstart () {// todo: add your control notification handler code hereupdatedata (true); info. nmillisecond = m_nmillisecond; info. pctrlprogress = & m_ctrlprogress; pthread = afxbeginthread (threadfunc, & info );}

    Add the statement to the function bool cmultithread3dlg: oninitdialog:

    {...... // Todo: add extra initialization herem_ctrlprogress.setrange (0, 99); m_nmillisecond = 10; updatedata (false); Return true; // return true unless you set the focus to a control}

    Add a thread handler:

    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 ;}

Use the MFC class library to program User Interface threads

To create a user interface thread:

  1. Use classwizard to create a cwinthread-like derived class (taking the cuithread class as an example)

     class cuithread: Public cwinthread {declare_dyncreate (cuithread) protected: cuithread (); // protected constructor used by dynamic creation // restart: // operationspublic: // overrides // classwizard generated virtual function overrides // {afx_virtual (cuithread) public: virtual bool initinstance (); Virtual int exitinstance (); //} afx_virtu Al // implementationprotected: Virtual ~ Cuithread (); // generated message map functions // {afx_msg (cuithread) // note-The classwizard will add and remove member functions here. //} afx_msgdeclare_message_map () }; 
  2. Overload functions: initinstance () and exitinstance ().
    Bool cuithread: initinstance () {cframewnd * WND = new cframewnd; WND-> Create (null, "UI thread window"); WND-> showwindow (sw_show ); WND-> updatewindow (); m_pmainwnd = WND; return true ;}

    Create a new user interface thread

    Void cuithreaddlg: onbutton1 () {cuithread * pthread = new cuithread (); pthread-> createthread ();}

    Note the following:

    A. Add a statement at the beginning of uithreaddlg. cpp:

    # Include "uithread. H"

    B. Change the feature of cuithread () constructor in uithread. h from protected to public.

    The execution sequence of the user interface thread is the same as that of the main application thread. First, call the initinstance () function of the user interface Thread class. If true is returned, continue to call the run () function of the thread, this function is used to run a standard message loop and is interrupted when a wm_quit message is received. During the message loop process, the run () function detects that the thread is idle (no message ), the onidle () function is also called, and the run () function is returned. The MFC calls the exitinstance () function to clear the resource.
    You can create a thread with no interface and a message loop. For example, you can derive a new class from cwinthread, complete a task in the initinstance function, and return false, this means that only the tasks in the initinstance function are executed without the message loop. You can use this method to complete the functions of a worker thread.

Routine 6 multithread6

  1. Create a project multithread6 Based on the dialog box. In the idd_multithread6_dialog dialog box, add the button idc_ui_thread, titled "User Interface thread"
  2. Right-click the project and select "New Class ..." Add the base class for the project as the cwinthread-derived Thread class cuithread.
  3. Add the new dialog box idd_uithreaddlg to the project. The title is "thread dialog box ".
  4. Create a cdialog-based class cuithreaddlg for the idd_uithreaddlg dialog box. Use classwizard to add the onlbuttondown message processing function to the cuithreaddlg class, as shown below:
    Void cuithreaddlg: onlbuttondown (uint nflags, cpoint point) {afxmessagebox ("You clicked the left button! "); Cdialog: onlbuttondown (nflags, point );}
  5. Add
    # Include "uithreaddlg. H"

    Add the protected variable cuithread m_dlg to the cuithread class:

    Class cuithread: Public cwinthread {declare_dyncreate (cuithread) protected: cuithread (); // protected constructor used by dynamic creation // attributespublic: // operationspublic: // overrides // classwizard generated virtual function overrides // {afx_virtual (cuithread) Public: Virtual bool initinstance (); Virtual int exitinstance (); ///} afx_virtual // implementationprotected: cuithreaddlg m_dlg; virtual ~ Cuithread (); // generated message map functions // {afx_msg (cuithread) // note-The classwizard will add and remove member functions here. //} afx_msgdeclare_message_map ()};
  6. The initinstance () and exitinstance () functions are reloaded respectively:
    Bool cuithread: initinstance () {m_dlg.create (rows); m_dlg.showwindow (sw_show); m_pmainwnd = & m_dlg; return true;} int cuithread: exitinstance () {m_dlg.destroywindow (); return cwinthread: exitinstance ();}
  7. Double-click the idc_ui_thread button to add the message response function:
    Void cmultithread6dlg: onuithread () {cwinthread * pthread = afxbeginthread (runtime_class (cuithread ));}

    Add the following content at the beginning of multithread6dlg. cpp:

    # Include "uithread. H"

Okay. Compile and run the program. Every time you click the "user interface thread" button, a thread dialog box is displayed. If you press the left mouse button in any thread dialog box, a message box is displayed.

(To be continued)

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.