Click here to Skip to main content
15,892,059 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
First, I briefly describe my code. My code collect data in 30Hz. If I use Ontimer, the code is no problem but when I use Multimedia timer, my code have an error:
VB
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp
Line: 946

This is my code (Not fully):
LONG CPredOTSDlg::nGetSystemTransformData( UINT wParam, LONG lParam )
{
	char pszTemp[256];
	CString szCBHandle, szPortNo;
	int nRow = -1;

	Rotation dtEulerRot;

	if (!m_bIsTracking)
		return 0;

	//UpdateData(true);

#if 0
	/* 
	 * if tracking mode is 0, we are asking for TX data, else we are
	 * asking for BX data.
	 */
	if ( m_nTrackingMode == 0 )
	{
		if ( !pCommandHandling->nGetTXTransforms( m_bUse0x0800Option ? true : false ) )
			return 0;
	} /* if */
	else if ( m_nTrackingMode == 1 )
	{
		if ( !pCommandHandling->nGetBXTransforms( m_bUse0x0800Option ? true : false ) )
			return 0;
	} /* else if */
#else
	if ( !pCommandHandling->nGetTXTransforms( false ) )
		return 0;
#endif

	/* check for system flags */
	//GetDlgItem(IDC_TEMPERATURE_NOTE)->SetWindowText(pCommandHandling->m_dtSystemInformation.bTemperatureOutOfRange ? _T("Temperature out of range") : _T("Temperature within range") );
	//GetDlgItem(IDC_DIAGNOSTICS_PENDING)->EnableWindow(pCommandHandling->m_dtSystemInformation.bDiagnosticsPending);

	//UpdateData(false);

	/* 
	 * if a new port has become occupied we do the following:
	 * 1) Stop tracking
	 * 2) Activate Ports
	 * 3) Start Tracking
	 */
	if ( pCommandHandling->m_dtSystemInformation.bPortOccupied )
	{
		if ( pCommandHandling->nStopTracking() &&
			 nActivatePorts() && 
			 pCommandHandling->nStartTracking() )
		{
			return 1;
		}/* if */

		/*
		 * We don't want the tracking thread to track if 
		 * activating the ports failed!
		 */
		m_bStopTracking = true;
		m_bIsTracking = FALSE;
		return 0;
	} /* if */

	for ( int i = 0; i < NO_HANDLES; i ++ )
	{
		if ( pCommandHandling->m_dtHandleInformation[i].HandleInfo.bInitialized > 0 &&
			 pCommandHandling->m_dtHandleInformation[i].szToolType[1] != _T('8') )
		{
			/* only update the frame if the handle isn't disabled*/
			if ( pCommandHandling->m_dtHandleInformation[i].Xfrms.ulFlags == TRANSFORM_VALID ||
				 pCommandHandling->m_dtHandleInformation[i].Xfrms.ulFlags == TRANSFORM_MISSING )
			{
				//m_szFrameNumber.Format( _T("%d"), pCommandHandling->m_dtHandleInformation[i].Xfrms.ulFrameNumber );
				UpdateData(false);
				//m_ctlFrameNo.RedrawWindow();
			}/* if */

			if( i == pCommandHandling->m_nRefHandle )
				sprintf( pszTemp, _T("R%02X"), i ); 
			else
				sprintf( pszTemp, _T("%02X"), i ); 

#if 0
			for ( int j = nRow+1; j < m_ctlTrackingList.GetItemCount(); j++ )
			{
				szPortNo = m_ctlTrackingList.GetItemText( j, 1 );
				if ( pCommandHandling->m_dtHandleInformation[i].szPhysicalPort == szPortNo )
				{
						nRow = j;
						break;
				} /* if */
				//nRow = -1;
			} /* for */
#endif
			/* fill the table */
			//m_ctlTrackingList.SetItemText( nRow, 0, pszTemp );
			if ( pCommandHandling->m_dtHandleInformation[i].Xfrms.ulFlags == TRANSFORM_VALID )
			{
				sprintf( pszTemp, _T("%.2f"), 
					pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.x );
				//m_ctlTrackingList.SetItemText( nRow, 2, pszTemp );
				sprintf( pszTemp, _T("%.2f"), 
					pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.y );
				//m_ctlTrackingList.SetItemText( nRow, 3, pszTemp );
				sprintf( pszTemp, _T("%.2f"), 
					pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.z );
				//m_ctlTrackingList.SetItemText( nRow, 4, pszTemp );
				if( !m_bUseEulerAngles )
				{
					sprintf( pszTemp, _T("%.4f"), 
						pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation.q0 );
					//m_ctlTrackingList.SetItemText( nRow, 5, pszTemp );
					sprintf( pszTemp, _T("%.4f"), 
						pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation.qx );
					//m_ctlTrackingList.SetItemText( nRow, 6, pszTemp );
					sprintf( pszTemp, _T("%.4f"), 
						pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation.qy );
					//m_ctlTrackingList.SetItemText( nRow, 7, pszTemp );
					sprintf( pszTemp, _T("%.4f"), 
						pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation.qz );
					//m_ctlTrackingList.SetItemText( nRow, 8, pszTemp );
				}
				else
				{
					CvtQuatToEulerRotation( &pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation,
											&dtEulerRot );
					sprintf( pszTemp, _T("%.4f"), dtEulerRot.fYaw );
					//m_ctlTrackingList.SetItemText( nRow, 5, pszTemp );
					sprintf( pszTemp, _T("%.4f"), dtEulerRot.fPitch );
					//m_ctlTrackingList.SetItemText( nRow, 6, pszTemp );
					sprintf( pszTemp, _T("%.4f"), dtEulerRot.fRoll );
					//m_ctlTrackingList.SetItemText( nRow, 7, pszTemp );
					sprintf( pszTemp, _T("") );
					//m_ctlTrackingList.SetItemText( nRow, 8, pszTemp );
				}
				sprintf( pszTemp, _T("%.4f"), 
					pCommandHandling->m_dtHandleInformation[i].Xfrms.fError );
				//m_ctlTrackingList.SetItemText( nRow, 9, pszTemp );

#if 0
				if ( pCommandHandling->m_dtHandleInformation[i].HandleInfo.bPartiallyOutOfVolume )
					//m_ctlTrackingList.SetItemText( nRow, 10, _T("POOV") );
				else if ( pCommandHandling->m_dtHandleInformation[i].HandleInfo.bOutOfVolume )
					//m_ctlTrackingList.SetItemText( nRow, 10, _T("OOV") );
				else
					//m_ctlTrackingList.SetItemText( nRow, 10, _T("OK") );
#endif
				
				//-> 20130322_hs.choi: 타이머에서 사용할 데이터 담기
				if(i == 1)
				{
					m_GantryX.px = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.x;
					m_GantryX.py = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.y;
					m_GantryX.pz = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.z;
					m_GantryX.rx = dtEulerRot.fYaw;
					m_GantryX.ry = dtEulerRot.fPitch;
					m_GantryX.rz = dtEulerRot.fRoll;
					CvtQuatToRotationMatrix(&pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation,m_motgRM);
				}
				else if(i == 2)
				{
					m_MeasuredX.px = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.x;
					m_MeasuredX.py = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.y;
					m_MeasuredX.pz = pCommandHandling->m_dtHandleInformation[i].Xfrms.translation.z;
					m_MeasuredX.rx = dtEulerRot.fYaw;
					m_MeasuredX.ry = dtEulerRot.fPitch;
					m_MeasuredX.rz = dtEulerRot.fRoll;
					CvtQuatToRotationMatrix(&pCommandHandling->m_dtHandleInformation[i].Xfrms.rotation,m_motxRM);
				}
				//<- 20140123_Hung

			}/* if */
#if 0
			else 
			{

				if ( pCommandHandling->m_dtHandleInformation[i].Xfrms.ulFlags == TRANSFORM_MISSING )
					m_ctlTrackingList.SetItemText( nRow, 2, _T("MISSING") );
				else
				{
					m_ctlTrackingList.SetItemText( nRow, 2, _T("DISABLED") );

					/* EC-03-0071 */
					if (m_ctlPortHandleCB.GetCurSel() >= 0)
					{
						m_ctlPortHandleCB.GetLBText( m_ctlPortHandleCB.GetCurSel(), szCBHandle );
						if ( !(strncmp( (LPSTR) (LPCSTR)szCBHandle, pszTemp, 2 )) &&
							 pCommandHandling->m_dtHandleInformation[i].HandleInfo.bEnabled )
						{
							/* if port has become DISABLED show it in the check box */
							m_szManufID = _T("");
							m_bPortEnabled = FALSE;
							m_bPortInitialized = FALSE;
							m_szSerialNo = _T("");
							m_szToolRev = _T("");
							m_szToolType = _T("");
							m_szPartNumber = _T("");
							UpdateData(false);
						} /* if */
					}

				} /* else */
				m_ctlTrackingList.SetItemText( nRow, 3, _T("---") );
				m_ctlTrackingList.SetItemText( nRow, 4, _T("---") );
				m_ctlTrackingList.SetItemText( nRow, 5, _T("---") );
				m_ctlTrackingList.SetItemText( nRow, 6, _T("---") );
				m_ctlTrackingList.SetItemText( nRow, 7, _T("---") );
				if( !m_bUseEulerAngles )
					m_ctlTrackingList.SetItemText( nRow, 8, _T("---") );
				else
					m_ctlTrackingList.SetItemText( nRow, 8, _T("") );
				m_ctlTrackingList.SetItemText( nRow, 9, _T("---") );
				if ( pCommandHandling->m_dtHandleInformation[i].HandleInfo.bPartiallyOutOfVolume )
					m_ctlTrackingList.SetItemText( nRow, 10, _T("POOV") );
				else if ( pCommandHandling->m_dtHandleInformation[i].HandleInfo.bOutOfVolume )
					m_ctlTrackingList.SetItemText( nRow, 10, _T("OOV") );
				else
					m_ctlTrackingList.SetItemText( nRow, 10, _T("---") );
			}/* else */	
#endif
		}/* if */
	}/* for */

	//m_ctlTrackingList.RedrawItems(0, m_ctlTrackingList.GetItemCount()-1);
	//m_ctlTrackingList.UpdateWindow();

	return 1;
} /* nGetSystemTransformData */

And when debugging it creates a breakpoint at line
C#
if( i == pCommandHandling->m_nRefHandle )
                sprintf( pszTemp, _T("R%02X"), i );
            else
                sprintf( pszTemp, _T("%02X"), i );

Here, is my callback function
void CALLBACK TimeProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
	CCriticalSection cs;
	CPredOTSDlg* obj = (CPredOTSDlg*) dwUser;
	//obj->MMTimerHandler(wTimerID);
	cs.Lock();
	obj->nGetSystemTransformData(0,0);	/* Get tumor position */
	cs.Unlock();
}

How can I solve this problem?
Posted
Comments
jeron1 1-Apr-14 11:51am    
It might help to post the method (code) within wincore.cpp where the assertion is occuring.
lephanhung 1-Apr-14 21:17pm    
Thank you for your help! This is a part of wincore.cpp
905 #ifdef _DEBUG
906 void CWnd::AssertValid() const
907 {
908 if (m_hWnd == NULL)
909 return; // null (unattached) windows are valid
910
911 // check for special wnd??? values
912 ASSERT(HWND_TOP == NULL); // same as desktop
913 if (m_hWnd == HWND_BOTTOM)
914 ASSERT(this == &CWnd::wndBottom);
915 else if (m_hWnd == HWND_TOPMOST)
916 ASSERT(this == &CWnd::wndTopMost);
917 else if (m_hWnd == HWND_NOTOPMOST)
918 ASSERT(this == &CWnd::wndNoTopMost);
919 else
920 {
921 // should be a normal window
922 ASSERT(::IsWindow(m_hWnd));
923
924 // should also be in the permanent or temporary handle map
925 CHandleMap* pMap = afxMapHWND();
926 ASSERT(pMap != NULL);
927
928 CObject* p=NULL;
929 if(pMap)
930 {
931 ASSERT( (p = pMap->LookupPermanent(m_hWnd)) != NULL ||
932 (p = pMap->LookupTemporary(m_hWnd)) != NULL);
933 }
934 ASSERT((CWnd*)p == this); // must be us
935
936 // Note: if either of the above asserts fire and you are
937 // writing a multithreaded application, it is likely that
938 // you have passed a C++ object from one thread to another
939 // and have used that object in a way that was not intended.
940 // (only simple inline wrapper functions should be used)
941 //
942 // In general, CWnd objects should be passed by HWND from
943 // one thread to another. The receiving thread can wrap
944 // the HWND with a CWnd object by using CWnd::FromHandle.
945 //
946 // It is dangerous to pass C++ objects from one thread to
947 // another, unless the objects are designed to be used in
948 // such a manner.
949 }
950 }
Rage 2-Apr-14 3:50am    
In what will that help ?
KarstenK 2-Apr-14 4:47am    
the most common cause of that problem is thread mismatch. It starts by creating the timer.

You better seperate GUI and data thread and syncronize the data in a GUI thread.

Show the code in which you create the data thread if you cant figure it out.
lephanhung 2-Apr-14 8:21am    
Yes! I think because the synchronization between CAllBACK and GUI. When I try to remove the code relative to GUI, it run without error. But when I add some code like Updatedata(), it will have error.
This is my code in header file:
// PredOTSDlg.h : header file
//

#pragma once

#define WM_FILL_LIST WM_USER+1
#define WM_COM_PORT_TO WM_USER+2
#define WM_CAL_PRE WM_USER+3
#define MODE_PRE_INIT 0x01
#define MODE_INIT 0x02
#define MODE_TRACKING 0x03
#define MODE_ACTIVATED 0x04

#include "CommandHandling.h" /* included the command handling header */
#include "XStructure.h" /* included the structure */
#include "PreFunc.h" /* included functions for pre-calculate */
#include "LMS.h" /* included Least Mean Squares Prediction */
#include "afxcmn.h"
#include <fstream>
#include "mmsystem.h"

#define MMTIMER
// CPredOTSDlg dialog
class CPredOTSDlg : public CDialogEx
{
// Construction
public:
CPredOTSDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_PREDOTS_DIALOG };
static void CALLBACK TimeProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
afx_msg void MMTimerHandler(UINT nIDEvent); /* mm_timer */

protected:
virtual BOOL DestroyWindow();
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// LMS prediction parameters
int m_iM;
int m_iDelta;
double m_dmux;
double m_dmuy;
double m_dmuz;
VW WeightVector;/* Declare Weight Vector*/

// Implementation
protected:
HICON m_hIcon;
CMenu * pMainMenu;

// mmtimer

UINT mmtimer; /* mm_timer periodic*/
UINT resolution; /* mm_timer resolution*/

// Generated message map functions

virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();

// Send message made by user
afx_msg LONG nGetSystemTransformData( UINT wParam, LONG lParam );
afx_msg LONG nComPortTimeout( UINT wParam, LONG lParam );
afx_msg LONG nCalculatePrediction( UINT wParam, LONG lParam );

// OTS system controller
afx_msg void OnBnClickedResetSystem();
afx_msg void OnBnClickedInitializeSystem();
afx_msg void OnBnClickedActivatePorts();
afx_msg void OnBnClickedTrackingBut();

// Declare some helpful function
afx_msg void Doclick(); /* Training button click will do in this function */
afx_msg void strf(); /* Shorten function for collecting and predicting */
afx_msg void outTxtFile(void); /* Export to TXT file */
afx_msg void outlistlog(void); /* Export to list log */
afx_msg void PredictionX(void); /* Predict px,py,pz */
afx_msg void SetWeightVector(void); /* Set initialization of Weight Vector */
afx_msg void DeleteDynamicMemory(void); /* Delete Memory used to allocate */

//afx_msg void MMTimerHandler(UINT nIDEvent); /* mm_timer */
afx_msg void StopTimer(); /* Stop mm_timer or on_timer */

// LMS prediction controller
afx_msg void OnBnClickedTrainingData();
afx_msg void OnBnClickedPredictionData();
afx_msg void OnBnClickedCalculateRms();

// Menu commander
afx_msg void OnSettingsComportsettings();
afx_msg void OnSettingsRomfilesettings();
afx_msg void OnSystemInitializesystem();
afx_msg void OnSystemActivatehandles();
afx_msg void OnSystemStarttracking();
afx_msg void OnSystemStoptracking();
afx_msg void OnViewSystemproperties();
afx_msg void OnViewDiagnosticalerts();
afx_msg void OnOptionsIlluminatorfiringrate();
afx_msg void OnOptionsProgramoptions();

// System
afx_msg void OnFileExit();
afx_msg void OnTimer(UINT_PTR nIDEvent);

// OTS
CCommandHandling *pCommandHandling; /* point to the command handling class */
bool m_bResetHardware; /* reset hardware variable */
bool m_bWireless; /* uses the wireless compatible settings */
bool m_bSystemInitialized; /* is the system initialized */
bool m_bPortsActivated; /* are ports activated */
int m_nCOMPort; /* the current com port number */
CString m_szSystemMode;
BOOL m_bUseEulerAngles;

/**********

1. you must use ON_THREAD_MESSAGE

2. is the buffer allocated from the actual thread and big enough

sprintf( m_szCommand, "TX %04X", nReplyMode );


3. PostThreadMessage(m_idThread, MM_PCB,0,0);//m_idThread must be target ie UI-Thread
 
Share this answer
 
it sound relativly easy: use PostThreadMessage from the callback (worker thread) with a own message ID to inform the GUI about new data.

Here should be demonstrated what I mean: PostThreadMessage Demystified[^]
 
Share this answer
 
Comments
lephanhung 3-Apr-14 7:59am    
I try to use PostThreadMessage, but i am not sure that my structure right or wrong. In header file:

#define MM_PCB WM_USER+4
DWORD threadProc(LPVOID lParam);
class CPredOTSDlg : public CDialogEx
{
// Construction
public:
CPredOTSDlg(CWnd* pParent = NULL); // standard constructor
LRESULT nOnThreadQuitFunction(WPARAM wParam, LPARAM lParam);
}

In cpp file:

/*****************************************************************
Global Variables
*****************************************************************/
DWORD m_idThread;
bool
m_bStopTracking, /* flag that tells the thread to stop tracking */
m_bIsTracking; /* flag that specifies if we are tracking */

UINT FillTrackingTable(LPVOID pParam); /* FillTrackingTable thread declaration */
void CALLBACK TimeProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CCriticalSection cs;
CPredOTSDlg* obj = (CPredOTSDlg*) dwUser;
//obj->MMTimerHandler(wTimerID);
cs.Lock();
//obj->nGetSystemTransformData(0,0); /* Get tumor position */
//obj->strf();
PostThreadMessage(m_idThread, MM_PCB,0,0);
cs.Unlock();
}
ON_MESSAGE(MM_PCB,&CPredOTSDlg::nOnThreadQuitFunction)

DWORD threadProc(LPVOID lParam)
{

MSG msg;
CPredOTSDlg *cs = new CPredOTSDlg;

while(GetMessage(&msg,0,0,0))
{
if(msg.message == MM_PCB)
{
cs->nGetSystemTransformData(0,0);
cs->strf();
}
DispatchMessage(&msg);
}
delete(cs);
return 0;
}

LRESULT CPredOTSDlg::nOnThreadQuitFunction(WPARAM wParam, LPARAM lParam)
{
return LRESULT(0);
}

But have an error : PredOTS.exe the 0x5a69ca31 (msvcr100d.dll) unhandled exceptions. 0xC0000005: 0xcdce92f9 position caused an access violation while recording.

The breakpoint shows these lines. These Lines from the library .h that i include when using the device.

memset(m_szCommand, 0, sizeof(m_szCommand));
sprintf( m_szCommand, "TX %04X", nReplyMode );

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900