Multi Threading Tutorial
www.supercamel.co.nr < this is my homepage.
A thread is a unit of execution for your application. Most programs execute instructions sequentially from the start to the end of your code. Multi threading allows more than one thread of execution. Basically this means you can do more than one thing at the same time. Imagine having two functions execute at once. Of course the CPU cannot actually execute two code paths simultaneously so it switches between threads during normal program flow. However, on a multi processor machine employing Symmetric Multi-Processing (SMP) more than one CPU can execute our program simultaneously. SMP is not supported by older versions of Windows (95/98/ME). A program carefully designed for multithreaded execution can outperform a single-threaded application in many circumstances. For example, one thread can handle sockets while another can handle the GUI. Each thread runs on a different application stack.
Have a look at this function
WINBASEAPI HANDLE
WINAPI CreateThread
(LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, PVOID, DWORD,
PDWORD);
The first parameter is a pointer to a security attributes structure. In this tutorial I will leave it as NULL. The second parameter is the size of the stack that you want the thread to run on. In this tutorial I will leave it at 0 to tell Windows NT that we want it to be the same size as the applications primary thread. The third parameter is the address of a function that you want your thread to execute. CreateThread expects this function to be declared as WINAPI. The fourth parameter is an argument that will be given to your threads function. It can be anything you want. The fifth parameter can be either 0 or CREATE_SUSPENDED. If you provide CREATE_SUSPENDED then your thread wont execute until you call ResumeThread(). If it is 0 then your thread will execute as soon as it is created. The last parameter is the address of an integer that will receive a unique thread ID. Every thread ID is different. The return value of this function is a handle to the thread.
Now we have that covered, lets make a thread!
__________________________________________________________________________________________________________________________________________________________
#include <iostream>
#include <windows.h>
using namespace std;
long
WINAPI Thread()
{
//print
this on the screen
cout << "Testing\n";
}
//execution starts here
int
main()
{
//we create
a thread that will execute Thread()
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, 0, 0, 0);
//Sleep
so the user can see the output displayed by the other thread
Sleep(3000);
}
__________________________________________________________________________________________________________________________________________________________
This is about as simple
as multithreading gets. When the program executes, it immediately creates a
thread. This thread outputs text while the main thread sleeps. Basically main()
and thread() execute at the same time. These threads are completely unsynchronised.
The next example passes
a variable to the thread function.
#include <iostream>
#include <windows.h>
using
namespace std;
class ThreadInfo
{
public:
int a, b, c;
};
//Thread() receives a pointer to threadinfo
long WINAPI Thread(ThreadInfo *threadinfo)
{
threadinfo -> a = 100;
threadinfo -> b = 200;
//we
change around with the values in threadinfo
threadinfo -> c = threadinfo -> a * threadinfo -> b;
}
int main()
{
ThreadInfo threadinfo;
//Create the thread
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, &threadinfo, 0, 0);
//Wait
for a moment to let the thread finish executing
Sleep(100);
//print threadinfo.c on the screen
cout
<< threadinfo.c << endl;
//Pause for a moment
Sleep(3000);
}
First I have created a
class with some integers in it. In the CreateThread function I provide a
pointer to this class. The CreateThread() function provides this as the
parameter for the Thread() function.
There is one problem, the first call to Sleep() is a bit of a shot in
the dark. We don’t know for sure that the thread has finished .Obviously
if this function hasn’t returned within 0.1 seconds then something is
wrong, but that isn’t the point. The WaitForSingleObject() function
solves this problem.
WINBASEAPI DWORD WINAPI WaitForSingleObject(HANDLE,DWORD);
WaitForSingleObject() waits until either the thread has terminated or the timeout value provided in the second parameter has elapsed. For this function we need the handle of the thread. MSDN recommends that all handles are closed with the CloseHandle() function before the program terminates.
So . . .
#include <iostream>
#include <windows.h>
using
namespace std;
class ThreadInfo
{
public:
int a, b, c;
};
//Thread() receives a pointer to threadinfo
long WINAPI Thread(ThreadInfo *threadinfo)
{
threadinfo -> a = 100;
threadinfo -> b = 200;
//we change around with the values in threadinfo
threadinfo -> c = threadinfo -> a * threadinfo -> b;
}
int main()
{
ThreadInfo threadinfo;
//Create the thread
HANDLE
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, &threadinfo, 0, 0);
//Wait for the thread to finish
WaitForSingleObject(hThread, 100);
//Close
the handle
CloseHandle(hThread);
//print
threadinfo.c on the screen
cout
<< threadinfo.c << endl;
//Pause for a moment
Sleep(3000);
}
Here are some other useful functions. Check out MSDN for more info
WINBASEAPI
DWORD WINAPI SuspendThread(HANDLE);
WINBASEAPI
DWORD WINAPI ResumeThread(HANDLE);
WINBASEAPI
HANDLE WINAPI GetCurrentThread(void);
WINBASEAPI
BOOL WINAPI GetExitCodeThread(HANDLE,PDWORD);
WINBASEAPI
BOOL WINAPI TerminateThread(HANDLE,DWORD);
SuspendThread() pauses a threads execution. The threads execution can be resumed with ResumeThread(). GetCurrentThread() returns a handle to the thread that the function was executed in. GetExitCodeThread retrieves the return value of a thread. TerminateThread() immediately terminates a thread.
Here’s a demo . . .
__________________________________________________________________________________________________________________________________________________________
#include <windows.h>
#include <stdio.h>
long WINAPI ThreadFunc()
{
HANDLE
hThisThread = GetCurrentThread();
SuspendThread(hThisThread);
CloseHandle(hThisThread);
return 12345;
}
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HANDLE
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc, 0, 0, 0);
MessageBox(NULL, "Test", "Test", MB_OK);
ResumeThread(hThread);
WaitForSingleObject(hThread, INFINITE);
DWORD a;
GetExitCodeThread(hThread, &a);
CloseHandle(hThread);
char msg[128];
sprintf(msg, "%d", a);
MessageBox(NULL, msg, "Test", MB_OK);
}
If this helps, send me an email