Sometimes we want to implement multi-threading in a class, the main thread gets the data at some point, can "notify" the child thread to process it, and then return the result. The following example is the main thread every 2s generates 10 random numbers, the 10 random number to the multithreaded class, so that it receives data immediately after printing.
First look at the definition of the class:
[CPP]View PlainCopy
- #pragma once
- #include <iostream>
- #include <atlbase.h>//Use of ATL classes
- #include <atlsync.h>
- #include <vector>
- Using namespace std;
- Class Cmultithreadtest
- {
- Public
- bool Init (); //Initialize class members
- bool UnInit (); //Release Resources
- void Notifydowork (const std::vector<int> &data);
- static DWORD CALLBACK testthread (lpvoid); //thread function, must be a static function
- DWORD TestProc (); //thread work implementation
- Private
- std::vector<int> m_data; //Sync data
- Atl::cevent m_notifyevent; //Notification Events
- HANDLE M_hthread; //thread handle
- };
The Alt class is used in the class and needs to contain the atlbase.h and altsync.h header files. The function Testthread must be a static function, because CreateThread only accepts global or static functions.
First look at the implementation of the Init () and UnInit () functions:
[CPP]View PlainCopy
- BOOL Cmultithreadtest::init ()
- {
- //Create Event
- BOOL bRet = m_notifyevent.create (null, TRUE, FALSE, NULL);
- if (!bret) {
- return false;
- }
- //Suspended way to create threads
- M_hthread = CreateThread (null, 0, &cmultithreadtest::testthread, this , create_suspended, NULL);
- if (NULL = = m_hthread) {
- return false;
- }
- //wake-up thread
- ResumeThread (M_hthread);
- return true;
- }
- BOOL Cmultithreadtest::uninit ()
- {
- //Notifies the thread to process data
- if (m_notifyevent! = NULL) {
- M_notifyevent.set ();
- }
- if (m_hthread! = NULL)
- {
- //reserved 100ms let the thread finish processing the data, 100ms is an estimate
- WaitForSingleObject (M_hthread, 100);
- CloseHandle (M_hthread);
- M_hthread = NULL;
- }
- return true;
- }
Atl::cevent member function create receives 4 parameters, the fourth parameter specifies the name of the event (it can have a name) so that the event can be found in other processes, where we do not need to use it, set it to null, other parameters are easy to understand, do not repeat.
The Init () function is worth noting that the thread we created is created in a suspended manner, so we must call the ResumeThread wakeup thread, otherwise the thread one value is asleep and no thread function is executed.
The UnInit () function is relatively straightforward, primarily informing the thread to perform the finishing touches and freeing the class's resources.
Let's take a look at the implementation of the remaining functions.
[CPP]View PlainCopy
- DWORD CALLBACK cmultithreadtest::testthread (lpvoid lpparam)
- {
- if (Lpparam = = NULL) {
- return 0;
- }
- Cmultithreadtest *lpthis = reinterpret_cast<cmultithreadtest *> (Lpparam);
- return Lpthis->testproc ();
- }
- DWORD Cmultithreadtest::testproc ()
- {
- While (true)
- {
- //5s listening every time, the number of seconds directly affect the performance of the program
- DWORD dwret = WaitForSingleObject (m_notifyevent, 5000);
- //Enter the Loop 5s No event occurred, do not do any processing
- if (Dwret = = wait_timeout) {
- continue;
- }
- //print array
- For (unsigned int i = 0; i < m_data.size (); i++)
- {
- cout <<m_data[i] <<"";
- }
- cout <<endl;
- //Reset Events
- M_notifyevent.reset ();
- }
- return 0;
- }
- void Cmultithreadtest::notifydowork (const std::vector<int> &data)
- {
- m_data = data;
- M_notifyevent.set (); //Notify the thread to do something!
- }
First we look at the Testthread function, which is the "portal" of the thread, and the thread is awakened after the function is executed. It is worth noting that when creating a thread, we pass the object pointer this as a parameter to the Create thread function, which is passed back when the system calls Testthread, where the weak type conversion is used reinterpret_ Cast converts the lpvoid into a pointer to the Cmultithreadtest class, reinterpret_cast is a dangerous type conversion, and generally applies only to conversions between pointers and integers. Interested students can refer to the C + + Primer 4th edition 18.2.1 chapter.
After the thread function converts the parameter lpparam to an object pointer, executes the object's member function TestProc (), TestProc () implements the primary logic. There may be questions here, why not implement the main logic directly in the Testthread () function? There are two advantages to this, one is the ability to separate the thread function logic from the business logic, and the second is that Testthread is a static function, the class static function can only handle static member variables of the class, and many times we want the thread to handle the non-static member variables of the class.
The last Notifydowork function is very simple, and the function is called externally, which assigns the externally transmitted data to the non-static member variable of the class M_data, and notifies the thread to process m_data data. TestProc the WaitForSingleObject function receives the event and executes it, and prints the m_data.
Let's look at the implementation of the main function:
[CPP]View PlainCopy
- int _tmain (int argc, _tchar* argv[])
- {
- Cmultithreadtest multithreadtest;
- //initialization failed
- if (!multithreadtest.init ()) {
- return 0;
- }
- Srand (unsigned int (time (NULL)));
- std::vector<int> data;
- While (true)
- {
- Data.clear ();
- //Generate 10 random numbers
- For (int i = 0; i <; i++)
- Data.push_back (rand ()% 1000);
- //Notify multithreaded class to perform work
- Multithreadtest.notifydowork (data);
- Sleep (2000);
- }
- Multithreadtest.uninit ();
- return 0;
- }
This code does not have to explain, remember to include the header files Windows.h, time.h and vector.
Summarize:
The usage scenario for multithreaded classes is that when a thread or data is obtained, it is expected that other threads will be able to handle this part number. Multithreaded class implementation is also relatively simple, first create thread and thread events, implemented to the external call interface, external through the interface set events, notify the thread to execute.
Windows Programming uses C + + to implement multithreaded classes