Click here to Skip to main content
15,884,388 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;

/**********

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 );
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
 

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