-
October 29th, 2005, 12:33 PM
#1
Problem with CEvent
hi ,
I have an aplication that has a dialog and inside this dialog I have another dialog that is on a work thread. When I show the outer dialog I run the thread on the inner dialog and have to wait its finish to continue working with the outer dialog. I dicided to use a CEvent to signilize the end of the thread. The problem is that when I compile the aplication in the line that I declared the CEvent object I recieved the error:
:\EstWin\CalcNota.cpp(103) : error C2143: syntax error : missing ';' before '*'
An on the references to CEvent object I got:
c:\EstWin\CalcNota.cpp(103) : error C2501: 'p::CEvent' : missing storage-class or type specifiers
c:\EstWin\CalcNota.cpp(103) : error C2501: 'p::Evento' : missing storage-class or type specifiers
c:\EstWin\CalcNota.cpp(109) : error C2039: 'Evento' : is not a member of 'p'
(p is the structure used to pass the parameters).
Related code:
Code:
struct p // structure used to pass the parameters.
{
CDialog* CDial;
CString String;
int* Semaforo;
bool bSoCotas;
CEvent* Evento; //--- Event to signilize the end of the thread
}Parametros;
....
//--- the outer dialog
BOOL CalcNota::Create(int* pSemaforo,CWnd* pWnd) //--- modeless.
{
Parametros.Evento = CreateEvent(NULL, TRUE, FALSE,"Calculo Nota De Serviço");
return CDialog::Create(IDD,pWnd);
}
//--- Thread function
//--- Calculanota is the inner dialog
UINT MyControllingFunction( LPVOID pParam ) //--- Thread for the inner calculation
{
CalculaNota CalculaNotaDeServico(Parametros.String,Parametros.CDial,Parametros.Semaforo,Parametros.bSoCotas);
CalculaNotaDeServico.MontaSecoes();
((CEvent*)((struct p*)pParam)->Evento)->SetEvent(); //---End of calculation
return 0;
}
...
//--- function that start the thread
void CalcNota::OnIniciarcalc()
{
CMainFrame* MainFrame = (CMainFrame*)AfxGetMainWnd();
CString NomeProj(((CMainFrame*)AfxGetMainWnd())->PegaProjetoAtual());
Parametros.String = ((CMainFrame*)AfxGetMainWnd())->PegaProjetoAtual();
Parametros.CDial = this;
Parametros.bSoCotas = IsDlgButtonChecked(IDC_CALCSOCOTA) != 0;
T = AfxBeginThread(MyControllingFunction,Parametros.Evento,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
T->m_pMainWnd = MainFrame;
T->ResumeThread(); //--- Executes the tread.
}
These erros usualy occurs when the header is not included. I seached on MSDN and there is no reference to header on this issue. What can be wrong?
Thanks in advance
-
October 29th, 2005, 05:40 PM
#2
Re: Problem with CEvent
CEvent is a MFC Class that makes Synchronization using Event Objects simple. To use CEvent, MSDN recommends that you include <afxmt.h>
Bug # 1: A case of incorrect pointer usage, here -
Code:
Parametros.Evento = CreateEvent(NULL, TRUE, FALSE,"Calculo Nota De Serviço");
Parametros.Evento is a pointer to a CEvent class object.
Fix # 1: Like a pointer to any other class you would instantiate a new object using new. Like this -
Code:
Parametros.Evento = new CEvent ();
Note that CreateEvent is a Win API that returns a HANDLE (and not a pointer to CEvent), and CEvent is a class that wraps the Win APIs that manage events.
So, the constructor of CEvent did the CreateEvent for you.
Bug # 2: Object passed to the thread type-casted to an object not passed.
When creating the worker thread, you pass the event as the parameter -
Originally Posted by Rabelo
Code:
T = AfxBeginThread(MyControllingFunction, Parametros.Evento,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
But, inside the thread function, you interpret the pointer as a structure -
Originally Posted by Rabelo
Code:
((CEvent*)((struct p*)pParam)->Evento)->SetEvent(); //---End of calculation
Clearly, the type-cast needs to be consistent. When you run the code, this will tend to crash.
Fix # 2: Pass a pointer to the structure.
Code:
Parametros.String = ((CMainFrame*)AfxGetMainWnd())->PegaProjetoAtual();
Parametros.CDial = this;
Parametros.bSoCotas = IsDlgButtonChecked(IDC_CALCSOCOTA) != 0;
T = AfxBeginThread(MyControllingFunction, &Parametros,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
I am presuming that Parametros is a global object. Note that p::Evento doesn't need to be a pointer to a CEvent object. As Parametros is global, this can be a CEvent object itself.
Events, and their usage is discussed in detail in this post.
Last edited by Siddhartha; October 29th, 2005 at 06:06 PM.
-
October 31st, 2005, 05:10 PM
#3
Re: Problem with CEvent
thank you very much, for your help and corrections.
-
October 31st, 2005, 05:24 PM
#4
Re: Problem with CEvent
You are welcome...
Another tiny point - Named Event objects are not necessary as in this case it seems that you are using events within the scope of the same application. Hence, the 4th parameter of CreateEvent can be NULL.
The HANDLE returned by CreateEvent is sufficient to use the same.
-
October 31st, 2005, 06:36 PM
#5
Re: Problem with CEvent
Originally Posted by Rabelo
I have an aplication that has a dialog and inside this dialog I have another dialog that is on a work thread. ...
As a general caution, it is usually difficult to design a program where the user interface (UI) is run from multiple different threads. Most people will advise you to avoid this architecture, and to run the UI strictly through a single thread. The other threads can post messages to the UI thread, and the messages will tell the UI thread what it should be displaying.
Mike
-
October 31st, 2005, 07:16 PM
#6
Re: Problem with CEvent
I´m still having problems... The WaitForSingleObject is returning WAIT_ABANDONED
See what I did:
on the outer dialog:
Code:
HANDLE Evento = NULL; // global
...
Evento = new CEvent(NULL,FALSE,FALSE,NULL);
DCalcNota.Create(Evento,this); //--- This is the inner dialog
DCalcNota.ShowWindow(TRUE);
DCalcNota.OnIniciarcalc();
DWORD YY;
YY = WaitForSingleObject(Evento,INFINITE); //<<< returning WAIT_ABANDONED
.....
in the inner dialog:
Code:
struct p //global
{
CDialog* CDial;
CString String;
bool bSoCotas;
HANDLE EventoFim;
}Parametros;
BOOL CalcNota::Create(HANDLE pEvento,CWnd* pWnd) //--- modeless.
{
Parametros.EventoFim = pEvento;
return CDialog::Create(IDD,pWnd);
}
...
UINT MyControllingFunction( LPVOID pParam )
{
CalculaNota CalculaNotaDeServico(Parametros.String,Parametros.CDial,Parametros.bSoCotas,Parametros.EventoFim);
CalculaNotaDeServico.MontaSecoes();
SetEvent(Parametros.EventoFim);
return 0;
}
void CalcNota::OnIniciarcalc()
{
CMainFrame* MainFrame = (CMainFrame*)AfxGetMainWnd();
CString NomeProj(((CMainFrame*)AfxGetMainWnd())->PegaProjetoAtual());
Parametros.String = ((CMainFrame*)AfxGetMainWnd())->PegaProjetoAtual();
Parametros.CDial = this;
Parametros.bSoCotas = false;
m_BUIniciar.EnableWindow(false);
m_BUPausa.EnableWindow(true);
m_BUCancelar.EnableWindow(false);
T = AfxBeginThread(MyControllingFunction,&Parametros,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
T->m_pMainWnd = MainFrame;
T->ResumeThread(); }
Thank you.
-
November 1st, 2005, 05:24 AM
#7
Re: Problem with CEvent
Code:
HANDLE Evento = NULL;
should be
and you don't need the "new CEvent" in this case : as has already been said the constructor of the CEvent class creates the handle for you.
The CEvent class has an operator overload so that it can be implicitly cast to HANDLE so you can still do
Code:
CEvent event;
::WaitForSingleObject(event, INFINITE);
It seems to me like you're mixing up Win32 calls with CEvent : CEvent handles all of these calls for you, so just stick to using its members when you can (i.e. SetEvent and ResetEvent are members).
Darwen.
Last edited by darwen; November 1st, 2005 at 05:27 AM.
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
|