Thank you all, guys. And I apologize for this delay. Let me address your points.

Quote Originally Posted by Igor Vartanov View Post
Exhaustive logging operations may help...
As you also pointed out, Igor, they can also interfere with the thread timings. I don't know if I mentioned this but I could not reproduce this behavior on my system. The only indication that this happens comes from event logs from a client. And as you also said remote debugging will be quite a cumbersome and probably futile way to address this issue since it will also introduce its own delay. As for minidumps I always had a hard time analyzing them.

Quote Originally Posted by Igor Vartanov View Post
Never trusted statements like this. You know why?
I agree. And I came off too pompous in it. I put it there so that people weren't asking me to check the synchronization, which was quite simple and shouldn't have caused any issues by itself. [PS. I'm sure this phrase doesn't help the original statement either ]


Quote Originally Posted by Arjay View Post
How about posting a snippet of the shared resources and how you are using the mutext to protect it? Btw, why are you using a mutex anyway?
I was originally using a critical section but then I had some doubts that maybe it was locking up with a possible repeated call or something, thus I reworked a synchronization object to use the wait on a mutex and a stop event together. Here's a code snippet for a synchronized object:
Code:
enum CS_SYNCH_OBJECTS{
	CAE_MUTEX,		//Synchronization mutex
	CAE_STOP_EVENT,		//Stop event

	CAE_COUNT		//MUST BE LAST!
};


//All calls are unfurled down to bare APIs for readability
struct SYNCHED_V1_DATA{
	SYNCHED_V1_DATA()
	{
		hCSMutex = ::CreateMutex(NULL, FALSE, NULL);
		nCntCSObjs = hCSMutex ? 1 : 0;
		hSynchObject[CAE_MUTEX] = hCSMutex;

		nV1 = 0;
	}
	~SYNCHED_V1_DATA()
	{
		UnloadAll();
	}
	void UnloadAll()
	{
		if(hCSMutex)
			CloseHandle(hCSMutex);
		hCSMutex = NULL;
		nCntCSObjs = 0;
	}
	BOOL Initialize(HANDLE hStopEvent)
	{
		//Initialize the synchronization objects with a "stop event"
		//RETURN: = TRUE if success
		if(hStopEvent)
		{
			hSynchObject[CAE_STOP_EVENT] = hStopEvent;
			nCntCSObjs = CAE_STOP_EVENT + 1;
		}

		return hSynchObject[CAE_STOP_EVENT] && hSynchObject[CAE_MUTEX] && nCntCSObjs == CAE_COUNT;
	}
	BOOL Get_nV1(int& v1)
	{
		//"GET" method
		//RETURN: TRUE if stop event is set (thus, need to exit ASAP w/o any further processing)
		BOOL bR = ::WaitForMultipleObjects(nCntCSObjs, hSynchObject, FALSE, INFINITE) == (WAIT_OBJECT_0 + CAE_STOP_EVENT);

		V1 = nV1;

		ReleaseMutex(hSynchObject[CAE_MUTEX]);
		return bR;
	}
	BOOL Set_nV1(int V1)
	{
		//"SET" method
		//RETURN: TRUE if stop event is set (thus, need to exit ASAP w/o any further processing)
		BOOL bR = ::WaitForMultipleObjects(nCntCSObjs, hSynchObject, FALSE, INFINITE) == (WAIT_OBJECT_0 + CAE_STOP_EVENT);

		nV1 = V1;

		ReleaseMutex(hSynchObject[CAE_MUTEX]);
		return bR;
	}

private:
	HANDLE hCSMutex;			//Synchronization mutex
	HANDLE hSynchObject[CAE_COUNT];		//Synchronization objects
	int nCntCSObjs;				//Number of valid objects in 'hSynchObject'

	int nV1;				//Object being synch'ed

	//Copy constructor and assignments are NOT available!
	//(Create new object instances instead)
	SYNCHED_V1_DATA(const SYNCHED_V1_DATA& s)
	{
	}
	SYNCHED_V1_DATA& operator = (const SYNCHED_V1_DATA& s)
	{
	}
};
Quote Originally Posted by Arjay View Post
As an idea of what can go wrong, consider the following code:
Code:
while( TRUE )
{
  switch( WaitForMultipleEvents( .... ) )
  case WAIT_OBJECT_0 + 0:   // Shutdown event
    return 1;
    break;
  case WAIT_OBJECT_0 + 1:
    DoGraphicsWork( ); 
    break;
  ... more switch cases 
}
Yes, that is exactly how it goes inside each worker thread, and I understand that if execution locks somewhere within DoGraphicsWork( ); it will pose a problem. But since it's a graphics rendering thread everything should be running (fairly) quickly within the DoGraphicsWork( ); method, that should definitely return within 5 second margin.


Quote Originally Posted by Alex F View Post
Does this happen only when stop event is set?
Yes.
Quote Originally Posted by Alex F View Post
hEventStopNow should be manual reset event
Yes, of course.

Quote Originally Posted by Alex F View Post
Every wait operation in both threads must include hEventStopNow
Yes, of course.

Quote Originally Posted by Zaccheus View Post
Could using GDI+ from a worker thread be causing problems?
Thank you for bringing it up because that was my main concern. In the back of my head I thought, "what if GDI+ does not support multi-threading like I do it here?" I still don't know the answer, by the way.


But I think I found a possible culprit for this issue (which is less mundane). I found one SendMessage in the worker thread that is calling to the main thread and that is a red flag #1. So I replaced it with a PostMessage and now have to wait if the glitch repeats again. (Which is quite painful by itself.)

On a side note, I want to ask you. This was always confusing for me, since some system APIs can call SendMessage themselves internally. One of my worker threads may call GetWindowLongPtr(GWL_STYLE), SetWindowLongPtr(GWL_STYLE) and SetWindowPos(). Can those APIs call SendMessage internally?