In this article, you will see a project sample for people like me who have just started to learn about multithreading.
MFC:
Win32:
Introduction
In some of my project development, the multithreading technologies turned out to be useful. And as usual, I looked at CodePoject and found the fine article Synchronization in Multithreaded Applications with MFC by Arman S. The idea and sub-script codes are good. It is a good starting point for multithreading habituation.
Just out of the routine, the demo implementation occurred to not be as good. It is a poor idea of drawing white rectangle in the old ellipse position before drawing the new ellipse. White space occurred visible while the ellipses overlapping.
Therefore, I've taken the liberty of improving the performance by means of the standard MSVS AppWizard procedures and added up some handling features.
Background
The article above was written in 2007, thus the project WorkerThreads
provided is not directly compatible with the latest versions of MSVS. Therefore, I've created a new single documented project named WorkerThreads
with MSVS-2012 pro, replaced codes of WorkerThreadsView.h and WorkerThreadsView.cpp with the same of the Arman S. project and included Thread.h and Thread.cpp from the same sources. The executable file compiled produced the video performance as follows:
In order to improve the performance above, I developed a new project InitThreads
. The executable InitThreads.exe has been built with MSVS-2012 pro.
Demo Explanations
Before you start building the project provided, it is highly recommended to have a look at the demo presentation enclosed in order to get an idea of the output expected.
Some menu and some special Accelerator keys arranged in order to demonstrate the InitThreads project implementation:
- File->New Ctrl + N - New Ball in random position with random velocity and random colour
- File->Delete Ctrl + D - Delete the Balls selected
- File->Reset Ctrl + R - Delete All the Balls
- File->Exit Alt + F4 - Exit Application
- Edit->Unselect All Ctrl + U - Unselect All the Balls selected if any
- Edit->Free Balls Ctrl + F - Balls moving transparently through each other
- Edit->Glancing Balls Ctrl + G -Balls are solid and not overlapping
- Edit->Bumping Balls Ctrl +B -Balls bumping elastic
- View->XOR Ctrl + X - Set/Reset XOR Overlapping
- View->Tool Bar - Show/Hide Tool Bar
- View->Status Bar - Show/Hide Status Bar
- Help->Help F1 - Show Help Dialog box
- Help->About InitThreads - Show About Dialog box
- Mouse Left Button Down - Select/Unselect Ball if Touched; Otherwise-New Ball in Cursor position with random velocity and random colour
All the commands above are also available on Help Dialog Box, just press F1 button:
The Help Dialog Box is non-modal, therefore you may select any command in the list control and press OK button or double click Mouse Left Button.
In the About Dialog Box, the reference to the original article by Arman S. is presented:
Building Notes.
Solution configuration must be installed as Release and the platform to be Win32.
The project provided has been developed with MSVS-2015 pro using the instruments of MSVS-2010. Therefore, the exe files are valid even for Windows-XP. If you do not need to run the application in Windows-XP, just change the instruments to MSVS-2015.
The default coding property is UNICODE; nevertheless MBCS coding is also available, just change the property.
Even if you are working for the first time with MSVS, just select menu Debug->Start without debugging and the program InitThreads.exe should start building and working.
Project Source and Data Storage
Standard source codes in InitThreadsproj
path have been created with the standard MFC Application Wizard:
- InitThreads.cpp, InitThreadsDoc.cpp - Defines the standard class behaviors for the application
InitThreadViewcpp
- Implementation of the standard CView
class; messages handling procedures created by the author using standard MFC Application Wizard procedures - BallThread.cpp - Derived from the standard MFC
CWinThread
class, overwritten by the author - InitThreads.rc and resource.h - Menu, dialog, accelerator resources created by the author using the standard Resource Wizard procedures
Code Explanation
All the Menu and Accelerator Commands have been done with standard MFC AppWizard technologies. Therefore, I feel nothing to explain better than in the standard tutorials. Key moments in solution:
-
Deriving new CBallThread
class from the standard MFC CWinThread
class:
class CBallThread : public CWinThread
{
DECLARE_DYNCREATE(CBallThread)
protected:
CBallThread(); public:
virtual ~CBallThread();
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
CPoint point; CInitThreadsView * m_pView; float x,y; float vx, vy; int m_nCount; BOOL m_bSelected; COLORREF m_color; void InitBall(CPoint point); UINT ThreadStep(void); void DrawMyBall(CDC * pDC); int Intersection( CBallThread * pB); protected:
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnIdle(LONG lCount);
};
-
Starting the new CBallThread
in the point designated (randomly if menu File->New command used or the cursor position if Mouse Left Button pressed):
void CInitThreadsView::StartBallThread(CPoint point)
{
CBallThread *pThread = (CBallThread *)AfxBeginThread(RUNTIME_CLASS(CBallThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pThread->point = point; pThread->m_pView = this; pThread->m_bAutoDelete = FALSE; pThread->ResumeThread(); m_BallList.AddTail(pThread); }
-
After the initialization, every thread moving by the steps in her own life:
UINT CBallThread::ThreadStep(void)
{
InitBall(point);
while (WAIT_TIMEOUT == ::WaitForSingleObject(g_eventEnd, 0)) {
CRect rectClient;
m_pView->GetClientRect(rectClient); CRect rectEllipse(Round(x) - m_pView->r, Round(y) - m_pView->r,
Round(x) + m_pView->r, Round(y) + m_pView->r);
int xt = rectEllipse.left - rectClient.left; if (xt <=0 ){vx *= -1; x -= xt;}
else
{ xt = rectClient.right - rectEllipse.right; if (xt <=0 ){vx *= -1;x += xt; }
}
int yt = rectEllipse.top - rectClient.top; if (yt <=0 ){vy *= -1; y -= yt;}
else
{yt = rectClient.bottom - rectEllipse.bottom; if (yt <=0 ){vy *= -1; y += yt;}
}
POSITION psn = m_pView->m_BallList.Find(this);
if(psn == NULL){ExitInstance(); Delete();} else
if(m_pView->m_bBumpingBalls || m_pView->m_bSolidBalls ) {m_pView->m_BallList.GetNext(psn);
for(POSITION pos = psn; pos != NULL;) {
CBallThread * ptr = (CBallThread *)m_pView->m_BallList.GetNext(pos);
Intersection(ptr);
}
}
x+=vx; y+=vy; Sleep(m_pView->m_nTick); }
return 0;
}
-
The complete scene of all the balls performed in m_nTick
milliseconds interval in the main View:
void CInitThreadsView::DrawScene(void)
{
CRect rect; GetClientRect(&rect);
dcMem.BitBlt(0, 0, rect.Width(), rect.Height(), NULL, 0, 0, WHITENESS);
int R2mode = m_bXOR ? dcMem.SetROP2(R2_NOTXORPEN) : dcMem.GetROP2();
for(POSITION pos = m_BallList.GetHeadPosition(); pos != NULL;)
{
CBallThread * ptr = (CBallThread *)m_BallList.GetNext(pos);
ptr->DrawMyBall(&dcMem);
}
dcMem.SetROP2(R2mode);
GetDC()->BitBlt(0, 0, rect.Width(), rect.Height(), &dcMem, 0, 0, SRCCOPY);
}
As for inner threads behavior, I think better to refer to the article by Arman S.
Your Own Applications Development using the Project Provided
You may pick up all this project, rename it with the project of my former CodeProject article "MFC Project from Existing Code in One Click" and combine and improve the codes as you like.
Your references to my codes, if any, should be highly appreciated.
Points of Interest and Acknowledgements
If you change the status of the balls intersection, you can observe different pictures of balls moving. Thus glancing blows look as follows:
From some comments to the first publicaion of this I discovered that some people are not happy with MFC performance. Especially for those people angry with MFC I developed Win32 project of the same with the same functions. In the sample below in Win32 version the balls allowed to overlap and picked out a speed as bumping blows:
It is worth nothing that this article and codes are not about graphics and balls' bumping. The idea is of creating the thread objects living there own life parallel to the main program.
I believe this project will be interesting for people who are just starting to study multithreading technologies.
Many thanks to Arman S. for his fine job. Also, my granddaughter likes to play with colour bubbles.
History
- 7th October, 2021: Initial version
- 17th October, 2021:Win32 project added and some corrections to MFC project done