Synchronising threads using Events in windows - multithreading

I need to synchronize threads using events. First I am not getting concept of Events in windows. I will take an example, I have main thread and secondary thread. I created a two events called "write" and "test". In main thread I signaled for 'write" event and waited on the "test" event. Both the events are getting signaled.
Basically I am porting an appli from linux to windows. The linux program uses condition variable to signaling the thread. Condition variable is not available in window XP.
Ex:
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 1
HANDLE ghWriteEvent;
HANDLE ghtestEvent;
HANDLE ghThreads[THREADCOUNT];
DWORD WINAPI ThreadProc(LPVOID);
void CreateEventsAndThreads(void)
{
int i;
DWORD dwThreadID;
ghWriteEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if (ghWriteEvent == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
ghtestEvent = CreateEvent(
NULL, // default security attributes
FALSE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if (ghtestEvent == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
// Create multiple threads to read from the buffer.
for(i = 0; i < THREADCOUNT; i++)
{
// TODO: More complex scenarios may require use of a parameter
// to the thread procedure, such as an event per thread to
// be used for synchronization.
ghThreads[i] = CreateThread(
NULL, // default security
0, // default stack size
ThreadProc, // name of the thread function
NULL, // no thread parameters
0, // default startup flags
&dwThreadID);
if (ghThreads[i] == NULL)
{
printf("CreateThread failed (%d)\n", GetLastError());
return;
}
}
}
void WriteToBuffer(VOID)
{
DWORD dwWaitResult;
printf("Main thread writing to the shared buffer...\n");
printf("Posting Events for %d\n",ghWriteEvent );
// Set ghWriteEvent to signaled
if (! SetEvent(ghWriteEvent) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return;
}
dwWaitResult= WaitForSingleObject(
ghtestEvent, // event handle
INFINITE); // indefinite wait
printf("WaitForSingleObject signelled (%d)\n", GetLastError());
if ( dwWaitResult == WAIT_OBJECT_0)
printf("Signlled State for %d with ret val : %d\n",ghtestEvent,dwWaitResult );
}
void CloseEvents()
{
// Close all event handles (currently, only one global handle).
CloseHandle(ghWriteEvent);
}
int main( void )
{
DWORD dwWaitResult;
CreateEventsAndThreads();
WriteToBuffer();
printf("Main thread waiting for threads to exit...\n");
// The handle for each thread is signaled when the thread is
// terminated.
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT, // number of handles in array
ghThreads, // array of thread handles
TRUE, // wait until all are signaled
INFINITE);
switch (dwWaitResult)
{
// All thread objects were signaled
case WAIT_OBJECT_0:
printf("All threads ended, cleaning up for application exit...\n");
break;
// An error occurred
default:
printf("WaitForMultipleObjects failed (%d)\n", GetLastError());
return 1;
}
// Close the events to clean up
CloseEvents();
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
// lpParam not used in this example.
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
printf("Thread %d waiting for write event...\n", GetCurrentThreadId());
dwWaitResult = WaitForSingleObject(
ghWriteEvent, // event handle
INFINITE); // indefinite wait
printf("rcvd event for Write is %d \n", ghWriteEvent);
switch (dwWaitResult)
{
// Event object was signaled
case WAIT_OBJECT_0:
WaitForSingleObject(
ghtestEvent, // event handle
INFINITE); // indefinite wait
printf("rcvd event for %d with Error %d\n", ghtestEvent,GetLastError());
if ( dwWaitResult == WAIT_OBJECT_0)
{
printf("Test event signaled for second thread \n");
}
break;
// An error occurred
default:
printf("Wait error (%d)\n", GetLastError());
printf("Wait error (%d)\n", GetLastError());
return 0;
}
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
Output of the program is:
Main thread writing to the shared buffer...
Posting Events for 2012
WaitForSingleObject signelled (183)
Signlled State for 2008 with ret val : 0
Main thread waiting for threads to exit...
Thread 2016 waiting for write event...
rcvd event for Write is 2012
rcvd event for 2008 with Error 0
Test event signaled for second thread
Thread 2016 exiting
All threads ended, cleaning up for application exit...

After a long struggle I found out the reason. If Two events are created with same Name, the second event while creating will throw an Error "ERROR_ALREADY_EXISTS (183).
If event are created with different name, it works without any issue. It is good programming to check the error and proceed accordingly.
ghtestEvent = CreateEvent(
NULL, // default security attributes
FALSE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if ( ERROR_ALREADY_EXISTS == GetLastError() )
{
printf("unable to create event (%d)\n".GetLastError());
exit(0);
}
Regards
JOhnnie

You only need to name events if you're going to use them to communicate between processes. You can pass NULL as the name if you're only synchronization threads within a single process.
When I'm creating named synchronization objects for inter-process communication, I generally give them a descriptive name (like "MyCompany - MyApp - WriteEvent") and tack on a GUID for good measure. You don't want to have a name conflict with some other developer who named his event "WriteEvent". The name can be up to MAX_PATH characters long and there is no performance penalty.

Related

Catch 22 with waiting for external application to finish processing and accidentally cancelling it before finishing

This is part of my code for launching an external application and waiting for it to finish:
DWORD WaitResult;
do
{
WaitResult = MsgWaitForMultipleObjects(1,
// only 1 wait object
&processInformation.hProcess, // worker thread
FALSE, // stop if any
INFINITE, // no timeout
QS_ALLINPUT);
if (WaitResult == WAIT_OBJECT_0 + 1)
{
// Handle windows message
MSG Msg;
while (PeekMessage(&Msg, nullptr, 0, (UINT)-1, PM_REMOVE))
{
TRACE3("%d %d %d\n", Msg.message, Msg.wParam, Msg.lParam);
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
} while (WaitResult != WAIT_OBJECT_0);
ASSERT(WaitResult == WAIT_OBJECT_0);
It is fine, until there is some issue with the calling exe that causes my app to indefinitely wait.
I did not put a figure for the time out because the exe being called is synchronizing calendar events with Outlook or Google. So depending on the users internet performance and the servers being synced with ...
Is there any way that I can safely add a time out that will not implement the actual process?

Kill a process after creating not working

I've somehow written a program to spawn a process but unable to kill it after 2 seconds automatically( It actually does not kill):
void createproc() {
//WaitForSingleObject(&processInfo.hProcess, INFINITE)
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
wchar_t commandline_args[] = L"\"C:\\ddnvnc\\WebServer.exe\" ";
if (!CreateProcess(NULL, // No module name (use command line)
commandline_args, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
MessageBox(NULL,
_T("Failed"),
_T("Windows Desktop Guided Tour"),
NULL);
}
Sleep(2000);
CloseHandle(&pi.hThread);
TerminateProcess(&pi.hProcess,0);
MessageBox(NULL,
_T("KIlled"),
_T("Windows Desktop Guided Tour"),
NULL);
}
What I want is to spawn and kill the process after 2 seconds, this will be in an infinite loop.
CloseHandle(&pi.hThread);
TerminateProcess(&pi.hProcess,0);
Use pi.hThread instead of &pi.hThread. Note that the order should be reversed.
You can use WaitForSingleObject instead of Sleep, and terminate the process only if it's not terminated already (for example by the user)
//Sleep(2000);
//TerminateProcess(pi.hProcess, 0);
if(WaitForSingleObject(pi.hProcess, 1000) == WAIT_TIMEOUT)
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);

Using SendMessageToDescendants between threads

In my MFC application I have a worker thread that listens on a network connection and as soon as some information has arrived I call SendMessageToDescendants to send that information via the lparam parameter. So every frame window will get the message and possibly process it via a message handler for the WM_SYNCHRONOTIFICATION message (WM_SYNCHRONOTIFICATION is a WM_APP+x message).
Code in the worker thread: (simplified for brevity)
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(&notificationmessage); // blocking until some information arrives
m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif));
// have all OnSynchroNotification handlers been called here ?
}
Message handler in the main thread:
LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2)
{
CNotificationMessage *pNotification = (CNotificationMessage*)p2;
// process message (ommited for brevity)
}
The code works fine, but I'm not sure if upon return from SendMessageToDescendants all OnSynchroNotification have been called.
The simplest solution to use is a counter. Before calling SendMessage, initialize a shared counter to the number of child windows you would like to have process the message. Each message handler is then responsible for decrementing the counter when it completes its work, and your event loop can check that the counter is 0 before generating more events. In pseudo C++:
unsigned int sharedCount; // global/static shared value
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(&notificationmessage); // blocking until some information arrives
unsigned int current = InterlockedCompareExchange(&sharedCount, activeWindowCount, 0);
if (current == 0)
{
m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif));
}
else
{
// Still processing the last message.
}
while (InterlockedCompareExchange(&sharedCount, 0, 0) != 0)
{
Sleep(100);
}
}
LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2)
{
// Processing
InterlockedDecrement(&sharedCount);
}
The slightly more complex solution, but the one I personally prefer, since you don't have to burn CPU waiting on completion, is to create an event for each message processing window, and then use WaitForMultipleObjects (or the Ex version) to halt the event loop until completion. Again, in pseudo C++:
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(&notificationmessage); // blocking until some information arrives
m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif));
DWORD waitResult = WaitForMultipleObjects(activeWindowCount, FrameEvents, TRUE, INFINITE);
if (waitResult == WAIT_OBJECT_0)
{
// Success
}
else if (waitResult == WAIT_FAILED)
{
// Failure: Use GetLastError() to figure out why the function call failed.
}
// Reset the events
}
LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2)
{
// Processing
SetEvent(thisFramesEvent);
}
This example uses an infinite timeout, but you can always set a reasonable timeout, and check for the return value WAIT_TIMEOUT to see if the time elapsed.
(Required Disclaimer: Error checking and variable initialization have been removed from both of these for the sake of brevity and readability. See the documentation for how to check for errors.)

Terminating a Worker thread from a Parent thread - MFC

I've just started with learning MFC and I'm writing one dialog based application for better understanding of Multi-Threading.
The main dialog has a progress bar, a Start button and a Cancel button.
On click of the start button, i'm creating a worker thread to do some processing(through API call) and the main thread takes care of Progress bar.
I've defined a couple of Windows Messages to update and stop Progress bar status
WM_UPDATE_CONTROL
WM_STOP_CONTROL
Below is the code that i've created so far
HWND* phObjectHandle;
CWinThread* thread;
void CprogCtrlDlg::OnBnClickedStart() {
phObjectHandle = new HWND; // Set object handle for Worker thread
*phObjectHandle = GetSafeHwnd();
// create worker thread
if(NULL == (thread = AfxBeginThread(ThreadFunc, phObjectHandle))) {
EndDialog(IDCANCEL);
}
AfxMessageBox(L"Thread started");
// Set Progress bar to marquee
}
void CprogCtrlDlg::OnBnClickedCancel() {
// kill the Worker thread
}
UINT CprogCtrlDlg::ThreadFunc(LPVOID pParam) {
HWND *pObjectHandle = static_cast<HWND *>(pParam);
CprogCtrlImpDlg* threadDlg = (CprogCtrlImpDlg*) pParam;
return threadDlg->ThreadFuncRun(pObjectHandle);
}
UINT CprogCtrlDlg::ThreadFuncRun(HWND* pObjectHandle) {
::PostMessage(*pObjectHandle, WM_UPDATE_CONTROL, 0, 0);
// repetitive API CALL in a loop
::PostMessage(*pObjectHandle, WM_STOP_CONTROL, 0, 0);
AfxMessageBox(L"Thread completed");
return 0;
}
I want to terminate the Worker thread from a Parent thread, if a Cancel button is clicked.
I tried using TerminateThread()(though it wasn't a suggested one) but I couldn't kill the thread.
Please comment and share your thoughts on terminating a worker thread from a parent thread.
I'm using visual studio 2010 on Windows 7
TIA
I would amend your code something like this.
Have some member variables in your dialog class to hold the thread handle and an event handle (initialise to NULL in the constructor):
CWinThread* m_hThread;
HANDLE m_hKillEvent;
Use a static function as your thread entry point, pass the dialog this as the parameter, then delegate the call back to the class instance so you have access to all of the dialog's variables:
UINT ThreadFunc(LPVOID pParam)
{
// static thread func - delegate to instance
CprogCtrlDlg* pDlg = static_cast<CprogCtrlDlg*>(pParam);
return pDlg->ThreadFuncRun();
}
When you start the thread, create an event too:
void CprogCtrlDlg::OnBnClickedStart()
{
// create worker thread
m_hKillEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = AfxBeginThread(ThreadFunc, this);
AfxMessageBox(L"Thread started");
}
To kill the thread, just set the event and wait on the thread handle, which will get signaled on death:
void CprogCtrlDlg::OnBnClickedCancel()
{
// kill the Worker thread
SetEvent(m_hKillEvent);
// wait for it to die
DWORD dwRet = WaitForSingleObject(m_hThread->m_hThread, 5000);
if (dwRet == WAIT_TIMEOUT)
{
// thread failed to die after 5 seconds
// error handling (maybe TerminateThread here)
}
}
In the thread function (now in the dialog class) you can post messages to yourself to indicate progress and use a wait on the event to catch a kill request:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
while (true)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
// ... so this is part of your working loop ...
PostMessage(WM_UPDATE_CONTROL, 0, 1 /*2,3,4,...*/);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}
I've left out initialisation, cleanup of pointers, handles etc. but you get the general idea I hope.
There are several ways you can code the thread loop, you can do it like above where you periodically check to see if the event is signaled, or you can wait on the event to get signaled to do the work. Both are common patterns and often used together with two events - one for triggering work and the other for killing. See this answer for some important points to note if waiting on multiple events.
For a simple progress bar update, you can put the event check inside the work loop, something like this:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
for (int i = 0; i < 100; ++i)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
PostMessage(WM_UPDATE_CONTROL, 0, (LPARAM)i);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}

how to create and update window in child thread using vc++

I just coded a child thread to create and update window but I am facing some problem. My window closes automatically after that thread execution is completed (naturally). But I don't want to close it so I tried putting a while loop in thread and in that loop I am calling InvalidateRect() function so that it can update window. Now window is not closing automatically but i can't move it or interact with it and cursor also showing some busy icon(means completely not responding). How I can solve that problem. below is code:
calling this from main()
bool CameraApp::OnInit()
{
hThread = (HANDLE)_beginthreadex( NULL, 0, &CameraFrame::StartCameraPreview,
NULL, 0, &threadID );
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
return TRUE;
}
Thread function block
unsigned __stdcall CameraFrame::StartCameraPreview( void* pArgs )
{
cFrame.ShowCameraWindow();
while(1)
{
cFrame.StartCapture();
InvalidateRect(hwnd, NULL, false);
Sleep(5000);
}
_endthreadex( 0 );
return 0;
}
i can't use main() function to create window. So, i have to use thread and update that window with periodic image taken from web-camera.
Instead of your infinite loop you need to create message pump in secondary thread that processes windows messages.
unsigned __stdcall CameraFrame::StartCameraPreview( void* pArgs )
{
cFrame.ShowCameraWindow();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_endthreadex( 0 );
return 0;
}

Resources