C provides a method of encapsulating objects, but does not provide multi-threaded support, if you need to generate multiple objects that simultaneously run, you need to define our own multi-thread class. "Using Multithreading and C To Generate Live Objects" in MSDN has made detailed introductions to this interesting technology.
Tony said, let's take a look at the structure that supports multi-threaded classes. The following is animate_Object as an example, first look at the constructor of Animate_Object:
Animated_Object :: Animated_Object (LPSTR LPIMAGENAME, SHORT STYPE)
{
hthread = CreateThread (NULL,
0,
(Lpthread_start_routine) ObjectThreadRoutine,
this,
0,
(LPDWORD) & this-> dwidthread;
iStatus = (hthread! = (Handle) NULL);
}
It can be seen that a thread, hthread is generated in the constructor, which is used to indicate the object contacted by the object, and use iStatus to successfully generate the thread, where Hthread is known as a private member, it is not known for the outside world, The only way to obtain the information of this object is through iStatus, which implements data package, and ISTATUS can also be used to represent all initialization works.
Below is a thread function. Since the thread function cannot be a non-static member function, you need a full-class function.
Long WinApi ObjectthreadRoutine (Animated_Object * fpobj)
{
Return (fpobj-> moveanddraw ());
}
The all-end function is actually a Stub Function, calls the member function MoveAndDraw of an Itemted_Object object inside the function, in order to let the global function can use the private function of animated_object, you need to declare the global function as a friend function of Animated_Object.
Here are the destructor
Animated_Object :: ~ Animated_Object (void)
{
IF (iStatus)
{
WaitforsingleObject (hthread, infinite);
CloseHandle (HTHREAD);
}
DeleteObject (Himage);
MessageBeep (-1);
}
When the object destructor, wait for the thread within the descent function, then turn off the thread, pay attention only when the initialization is successful (iStatus is not 0), the only problem is: if the thread If you call the destructuring function, you will generate a deadlock (a call B, B returned is that A is over), here you can use PostMessage, especially note that if you use SendMessage, you can still generate a deadlock (you can use Method for shared variables to avoid deadlocks) Close-off, use PostMessage in the thread function to turn off your own messages to the external control thread, and turn off the thread by external control threads, which will not generate a deadlock when the destructor is called. The problem.
Synchronous Problem: When a plurality of instances are generated, if you need to access shared variables, you need to use mutex synchronous methods. Below is the core part of Animated_Object :: MoveAndDraw (void)
{INT ITEMPX, ITEMPY;
HDC HDC;
While (! bfinished)
{
Itempx = ix ixvelocity;
Itempy = IY IYVELOCITY;
/ * The Next Four if Statements Check WHETHER A WALL HAS BEEN HIT AFTER A MOVE.
If Yes, The position is reset to the wall, the direction reverse,
And a random value added. * /
EntercriticalSection (& CSSerializedRAW); HDC = getdc (the_pond-> hwndapplication); Bitblt (HDC, IX, IY, IIMAGEWIDTH, IIMAGEHEHT, NULL, 0, 0, WHITENESS); IX = itempx; Iy = itempy; Icalories- = move_deduction; / * Do Three Things here to determine WHETHER One Has Died: * / / * (a) Do Additional per-move work, depending on the object type. * / / * (b) DETERMINE WHETHER WE HAVE ENOUGH Fuel Left to Survive. * / / * (c) Ask the Pond WHETHER A Collision Has Occurred. * / IF (! ObjectspecificThreadRoutine (HDC) || // Look here! Icalories <0 || ! The_pond-> Newcoordinates (iHandle, IX, IY)) bfinished = true; Else / * Redraw the object. * / ReleaseDC (THE_POND-> HWndApplication, HDC); LeavecriticalSection (& CSSerializedraw); / * Delay the Object Before moving on. * / Sleep (delay); }; // end of while loop. Going Past Here Means We Are Dead ... / * Inform The window That the thread Has Terminated, SO IT CAN Clean Up The Object. * / Postmessage (THE_POND-> HWndApplication, WM_Object_died, (wparam) iHandle, NULL; Return (TRUE); }