Win32 multithreading-use multithreading In the MFC Program

Source: Internet
Author: User
1. Basic Knowledge

It should be clear that when creating multiple threads in the MFC program, you should call the thread interface function afxbeginthread () designed for us in the MFC program (), the reason is that this interface initializes the MFC function and data for us. If you do not use any MFC function or data in the multi-thread of MFC, you can also use this function to create multiple threads. Now, let's go to the topic. I will introduce two call methods for creating a worker thread and a UI thread using afxbeginthread.


Both the user interface thread and worker thread are created by afxbeginthread. MFC provides two overloaded versions of afxbeginthread, one for the worker thread and the other for the user interface thread, which have the following prototype and process:

The prototype of afxbeginthread of the worker thread is as follows:
Cwinthread * afxapi afxbeginthread (
Afx_threadproc pfnthreadproc,
Lpvoid pparam,
Int npriority,
Uint nstacksize,
DWORD dwcreateflags,
Lpsecurity_attributes lpsecurityattrs)
Where:
The entry function of parameter 1 must be declared as follows: uint mythreadfunction (lpvoid pparam );
Parameter 2 is the parameter passed into the thread. Note that its type is lpvoid, so we can pass a struct into the thread.
Parameters 3, 4, and 5 respectively specify the thread priority, stack size, creation ID, and security attributes, meaning the same as the user interface thread.

The afxbeginthread prototype of the user interface thread is as follows:
Cwinthread * afxapi afxbeginthread (
Cruntimeclass * pthreadclass,
Int npriority,
Uint nstacksize,
DWORD dwcreateflags,
Lpsecurity_attributes lpsecurityattrs)
Where:
Parameter 1 is the runtime_class class derived from cwinthread;
Parameter 2 specifies the thread priority. If it is 0, it is the same as the thread that created the thread;
Parameter 3 specifies the thread stack size. If it is 0, it is the same as the thread that created the thread;
Parameter 4 is a creation identifier. If it is create_suincluded, a thread is created in the suspension state, and the thread is suspended after the thread is created. Otherwise, the thread starts executing after the creation.
Parameter 5 indicates the thread security attribute, which is useful in NT.

The returned value of the afxbeginthread () function is the cwinthread * pointer, but this pointer cannot be used directly because it will be automatically destroyed. If you use this pointer directly, when you operate on this pointer, if it has been destroyed by MFC, access violations will come.
For how to use the returned values, see a piece of MFC program I wrote.

Cstring strname = _ T (""); cwinthread * pthread = NULL; uint cbcgtestdlg: threadworkfunc (lpvoid) {for (INT n = 0; n <10000; N ++) {strname = _ T ("http://blog.csdn.net/windows_nt"); strname = strname + _ T ("\ n"); trace (strname) ;}return 0 ;} void cbcgtestdlg: onok () {for (INT n = 0; n <10000; ++ N) {If (pthread) {waitforsingleobject (pthread-> m_hthread, infinite ); delete pthread;} pthread = afxbeginthread (thre Adworkfunc, null, 0, create_suincluded, null); If (pthread) {pthread-> m_bautodelete = false; pthread-> resumethread ();}}} // now you can safely use the returned pthread, but remember to call Delete pthread after use, release resources (the thread handle in the cwinthread class will be automatically released in the destructor ).

2. Multiple Threads in MFC

There is no difference between the use of worker threads and the use of multithreading in C ++. Please refer to the four methods of thread synchronization I have previously written:
Windows core programming-key section (critical section) thread synchronization
Windows core programming-mutexes)
Windows core programming-semaphores (semaphore)
Windows core programming-kernel object Thread Synchronization

Next, I will introduce some knowledge about UI threads.
The UI thread version of afxbeginthread (). It is expected that you configure an object for the class specified in the pthreadclass parameter. This class must be derived from cwinthread. cwinthread provides a bunch of diverse virtual functions, you can rewrite it to help message processing, thread startup and cleanup, and Exception Handling. These virtual functions are listed as follows:
Initinstance ()
Exitinstance ()
Onidle ()
Pretranslatemessage ()
Isidlemessage ()
Processwndprocexception ()
Processmessagefilter ()
Run ()
Of course, you do not have to rewrite them. By default, as long as initinstance () is rewritten, MFC starts a message loop.

3. Restrictions on multi-thread MFC data sharing in MFC

There is a major limitation on the multi-threaded program of MFC, which will affect almost everything you do. The ing relationships between various MFC objects and Win32 handles are recorded in the Thread Local Storage (SLS. Therefore, you cannot hand an MFC object from a thread to another thread, and you cannot pass an MFC Object Pointer between threads. My so-called MFC objects include (but are not limited) cwnd, CDC, cpen, cbrush, cfont, cbitmap, cpalette, the existence of this restriction prevents the necessity of "generating a synchronization mechanism for these objects", which will greatly affect the speed and efficiency of MFC.

This restriction has several differences. If both threads call cwnd: getdlgitem () to obtain a control (such as edit) in the dialog box ), then each thread should get a different pointer-even if the objects of the two threads are a control. If a pointer is given, and the object it refers to does not have a permanent MFC structure, when a request action for the pointer appears, MFC will usually generate some temporary objects. For example, cwnd: getdlgitem () generates a temporary object when a pointer (for example, pointing to a cedit * or a cstatic *) is obtained. These objects will be cleared when the next program enters the idle loop. If these objects are shared by many threads, MFC will not be able to predict their life, and therefore will not be able to execute cleanup. Therefore, MFC generates a new object for every required thread.
This restriction (about switching objects between threads) means that you cannot put a pointer (pointing to a cwnd) into the structure, which is used by a worker, you cannot give a pointer to cdialog or cview to another thread. When you need to call a member function in view or document, especially a function like updateallviews (), the above restrictions will soon deteriorate.
MFC checks "usage of objects across Threads" in many places ". At any time, as long as MFC calls assert_valid to the object, it will check whether the object is kept in the Thread Local Storage (TLS). If you try to call a file like cdocument: updateallviews () when the program runs such a function, cwnd: assertvalid () will generate an assertion.

The following comments appear in the cwnd: assert_valid () member function of wincore. cpp in the source code of MFC.
// Note: if either of the above asserts fire and you are
// Writing a multithreaded application, it is likely that
// You have passed a C ++ object from one thread to another
// And have used that object in a way that was not intended.
// (Only simple inline wrapper functions shoshould be used)
//
// In general, cwnd objects shoshould be passed by hwnd from
// One thread to another. The processing thread can wrap
// The hwnd with a cwnd object by using cwnd: fromhandle.
//
// It is dangerous to pass C ++ objects from one thread
// Another, unless the objects are designed to be used in
// Such a manner.
The use of local thread storage (TLS) illustrates the importance of using afxbeginthread () to generate a UI thread in an MFC program. If you use _ beginthreadex () or creatthread (), MFC will not give you the opportunity to generate the necessary structure to maintain its handles.
There is an inconvenient alternative to sharing objects between threads: do not place the MFC object and change the handle of the object. When you pass handle to a new thread, the thread can attach the handle to a new MFC object: Using fromhandle () can generate a temporary object, using attach () A permanent object can be generated. For example, if you submit an HDC to a thread, you can use the following code to attach the HDC to a permanent CDC object:

// 1. Use HDC horiginaldc for a long time; // The received hdccdc DC; DC. attach (horiginaldc); // map the DC here. detach (); // call detach () before the thread exits; // 2. If the thread only wants to use this value temporarily, it can generate a temporary object, like this: // CDC * PDC = CDC: fromhandle (horiginaldc );

Not all MFC objects are easily transmitted using this technology. Cview is an example. You can easily obtain a view's window handle and hand it over to a new thread, but it is best that the new thread can attach this handle to a cwnd, because no cview: fromhandle () function can generate a temporary view, which reflects the original one like a mirror. The original cview structure is no longer available. Therefore, all related view information is no longer available. Return to updateallviews (). The pointer used during function operation is buried in document and cannot be changed. Therefore, other threads do not have any way to call this function. The only alternative is to send a custom message, return to the original thread, and tell it to update its views.

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.