-
March 4th, 2004, 03:27 PM
#1
AfxBeginThread throws exception
The Document in my SDI application owns an object that takes care of some seriall communication the class is called CSerComm.
In Document .h file
CSerComm m_SerCommObj;
Since the worker thread should be created at start up a function in the Document is called in InitInstance which will create the thread. The Document function is called StartThread()
In InitInstance function
Code:
//Get Document pointer
POSITION pos = this->GetFirstDocTemplatePosition();
CGsdoc_b1Doc* pDoc = (CGsdoc_b1Doc*)this->GetNextDocTemplate(pos);
//Open the document
if(!((CDocTemplate*)pDocTemplate)->OpenDocumentFile(docFile))
{
pDoc->OnSaveDocument(docFile);
pDoc->OnOpenDocument(docFile);
}//create file if application run first time
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
//Signal to Document to create the thread
pDoc->StartThread();
In StartThread a CSerComm function is called that the StartThread
Code:
m_SerCommObj.CreateThread(); //start communication
In CreateThread() function AfxBeginThread is called
m_pThread = AfxBeginThread(ThreadFunc, this);
But an exception is thrown when AfxBeginThread is called.
Why is that?
It works better if I let the Application class own the CSerrComm object or if the m_SerCommObj.CreateThread() is called in the OnNewDocument function in the Document. But this does'nt suite other requierments.
[Andreas]: Added code tags...
Last edited by Andreas Masur; March 6th, 2004 at 05:29 AM.
-
March 4th, 2004, 04:36 PM
#2
which exception? run your code under a debugger...
-
March 4th, 2004, 05:12 PM
#3
the function you call... is it declared as the following:
at your .h
Code:
static UINT Function(LPVOID parameter);
at your .ccp
Code:
UINT CDlg::Function(LPVOID parameter)
{
return 1;
}
-
March 5th, 2004, 12:45 AM
#4
Interesting.
First call GetLastError(). Post the interface of the thread's callback function.
Kuphryn
-
March 5th, 2004, 01:57 AM
#5
Ok here comes the the thread controlling function. After that the StartThread function.
Code:
//Thread controlling function implementation
//Seriall communication read/write is done in this function
UINT CSerComm :: ThreadFunc(LPVOID pvParam)
{
COMMTIMEOUTS myCommTimeouts;
int addr = 1;
DCB my_dcb = {0};
HANDLE Port;
DWORD error;
POSITION appPos, docPos;
int comPort = 0;
CString comStr = "Com1";
MSG msg;
CWinApp* theApp;
CDocTemplate* docTemplate;
CGsdoc_b1Doc* pDoc;
bool portSetFlag = false;
CString strWrite;
int i = 0;
int grytAdresser[110]; //Innehåller adresser (ID) till grytorna
for(i=0; i<110; i++)
{
grytAdresser[i] = 0;
}//Initiera gytadress vektorn till 0
while(1)
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
{
if( msg.message == UM_SET_PORT)
{
//Set port settings theApp = AfxGetApp();
appPos = theApp- >GetFirstDocTemplatePosition();
error = GetLastError();
docTemplate = theApp- >GetNextDocTemplate(appPos);
docPos = docTemplate- >GetFirstDocPosition();
pDoc = (CGsdoc_b1Doc*)docTemplate- >GetNextDoc(docPos);
comPort = pDoc->GetComPort();
if(portSetFlag == true)
CloseHandle(Port);
//If same com port is picked by user
comStr.Format("%s%d", "Com", comPort);
Port = CreateFile(comStr,
GENERIC_READ | GENERIC_WRITE,
0, '\0',
OPEN_EXISTING, 0,
'\0');
portSetFlag = true;
if(Port == INVALID_HANDLE_VALUE)
{
AfxMessageBox("Could not create port");
return 1;
} // error opening port; abort
if(!GetCommState(Port, &my_dcb))
{
AfxMessageBox("Didn't Get DCB");
error = GetLastError();
//error getting comm state
}
my_dcb.BaudRate = CBR_9600;
my_dcb.fParity = 0;
my_dcb.fOutxCtsFlow = false;
my_dcb.fOutxDsrFlow = false;
my_dcb.fDtrControl = DTR_CONTROL_DISABLE;
my_dcb.fDsrSensitivity = false;
my_dcb.fOutX = false;
my_dcb.fInX = false;
my_dcb.fRtsControl = RTS_CONTROL_DISABLE;
my_dcb.ByteSize = 8;
my_dcb.Parity = NOPARITY;
my_dcb.StopBits = ONESTOPBIT;
//Set timeout structure
myCommTimeouts.ReadIntervalTimeout = 0;
myCommTimeouts.ReadTotalTimeoutMultiplier = 0;
myCommTimeouts.ReadTotalTimeoutConstant = 500;
myCommTimeouts.WriteTotalTimeoutMultiplier = 0;
myCommTimeouts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(Port, &myCommTimeouts))
AfxMessageBox("failed to set Com timeout");
if(!SetCommState(Port, &my_dcb))
{
AfxMessageBox("Failed to set up Com port");
error = GetLastError();
return(0);
}
}//Set port
else if(msg.message == UM_FINISH_THREAD)
{
ExitThread(1);
}//Exit thread
else if(msg.message == UM_POT_ADDED)
{
theApp = AfxGetApp();
appPos = theApp->GetFirstDocTemplatePosition();
error = GetLastError();
docTemplate = theApp->GetNextDocTemplate(appPos);
docPos = docTemplate->GetFirstDocPosition();
pDoc=(CGsdoc_b1Doc*)docTemplate->GetNextDoc(docPos);
for(i=0; i<(pDoc->m_PotKeyArr.GetSize()); i++)
{
grytAdresser[i] = pDoc->m_PotKeyArr[i];
}
}
else if(msg.message == UM_SEND)
{
addr = 1;
StartJadekCom(Port, addr, ComReadTempLogg);
strWrite.Format("%s%d", "Meddelande av ", addr);
AfxMessageBox(strWrite);
/* JADEK har ändrat */
GetJadekCom(Port, addr, ComReadTempLogg);
if(TempLogg.ComStatus == 0 ){
StartJadekCom(Port, addr, ComReadTempLogg);
strWrite = "Ack skickad!";
AfxMessageBox(strWrite);
}
else {
switch( TempLogg.ComStatus ){
case ComErrStartBit:
strWrite.Format("%s", "Error: Startbit");
break;
case ComErrAdress:
strWrite.Format("%s", "Error: Adress");
break;
case ComErrMedTyp:
strWrite.Format("%s", "Error: Meddelandetyp");
break;
case ComErrCheckSum:
strWrite.Format("%s", "Error: Checksumma");
break;
default:
strWrite.Format("%s", "Error: Okänd" );
break;
}
AfxMessageBox(strWrite);
}
::Sleep(10);
}
}
AfxMessageBox("return 0");
return 0;
}
The StartHandler declaration in the Document .h file
Code:
void StartThread();
StartHandler in the Document .cpp file
Code:
void CGsdoc_b1Doc::StartThread()
{
m_SerCommObj.CreateThread(); //start communication
//Set port message
::PostThreadMessage(m_SerCommObj.GetThreadId(), UM_SET_PORT, 0, 0);
}
Sorry for the poor indention I hope it's readable.
[Andreas]: Added code tags...
Last edited by Andreas Masur; March 6th, 2004 at 05:29 AM.
-
March 5th, 2004, 02:24 PM
#6
By the way ThreadFunc is declared
static UINT
-
March 5th, 2004, 03:52 PM
#7
You did not answer the question "which exception". The original post of this thread should have specified what the exception is; just saying "an exception is thrown" is inadequate. The question is probably meaningless without specifying the exception and what line of your source code gets the exception.
Please use the code tags for your source code. It is very easy to do. Also, when using the code tags, ensure that the lines are not too wide; you can split lines one way or another to make them not too wide.
I think I see the problem but if I do then you would also see the problem if you simply look at the call stack when the exception occurs.
-
March 5th, 2004, 04:28 PM
#8
The dialog box that pops up saya that I don't handle the exception and that it is an
"Access violation"
exception.
I don't know how to look at the call stack.
-
March 5th, 2004, 04:49 PM
#9
You must know how to look at the call stack. It is a critical debugging tool. So when you get the dialog box saying you have an exception, click the button to debug. Then in the menus select "View | Debug Windows | Call Stack". The Call Stack will then be shown. In the call stack there is one line for each function called. The top line is the function called most recently and is where the exception occured. However it is usually in MFC code or Windows code that the error occurs. So we need to go down to the topmost line for a fuction in our code. That is the line in our program that is getting the error. Often the problem is obvious as soon as we see the line in our program that is getting a problem.
-
March 5th, 2004, 05:22 PM
#10
Thanks for helping me out here.
In the call stack I see
CSerComm::CreateThread() line 78 + 28 bytes
CGsdoc_b1Doc::StartThread() line 609
CGsdoc_b1App::InitInstance() line 156
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x001327b2, int 1) line 39 + 11 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x001327b2, int 1) line 30
WinMainCRTStartup() line 330 + 54 bytes
KERNEL32! 7c5987e7()
So the error occured in the CSerComm::CreateThread() on line 78. This where AfxBeginThread is called.
CreateThread looks like
bool CSerComm :: CreateThread()
{
CWnd* p_wnd = AfxGetMainWnd();
m_pThread = AfxBeginThread(ThreadFunc, this);
if(!m_pThread)
{
// Could not create thread
return false;
}
m_pThread->m_bAutoDelete = true;
m_ThreadID = m_pThread->m_nThreadID;
return true;
}
-
March 5th, 2004, 05:28 PM
#11
Originally posted by Sam Hobbs
Please use the code tags for your source code. It is very easy to do.
-
March 5th, 2004, 05:42 PM
#12
I forgot to mention that if you double-click on a lin in the call stack, you will be shown the source code line corresponding to that line.
I don't know why the AfxBeginThread function would get an exception.
Note that in CSerComm :: ThreadFunc the variable theApp is used without being initialized. It is set later, but not initially. That is nearly guranteed to be an error, but I assume it would show in the call stack. I assume the debugger would show the call stack for the thread, but perhaps there is something more that needs to be done when debugging threads.
You can put a breakpoint at the beginning of CSerComm :: ThreadFunc to see if it is executed. If you reach the breakpoint then you know the problem is nearly certainly the uninitialized theApp. You can single-step to see if execution does in fact get to the first line that uses theApp. You can do all this without recompiling. It would be a useful way to learn about debugging.
Also, you can edit your previous posts and add [Code] and [/Code] tags.
-
March 5th, 2004, 07:17 PM
#13
No you'll get the thread context/stack in the stack view (well most debuggers if not all will show it) the IDE (along with others) you can switch to threads and view the stack of the current thread. You should easily be able to tell which * is causing the problem by just clicking on the line in the stack trace.
-
March 6th, 2004, 05:26 AM
#14
-
March 6th, 2004, 05:30 AM
#15
Originally posted by martenbengtsson
The dialog box that pops up saya that I don't handle the exception and that it is an
"Access violation"
exception.
Well...an access violation is different from a thrown exception...it looks like you are trying to access any window etc. from your thread before it is created...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|