CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335

    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

  2. #2
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    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 -
    Quote 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 -
    Quote 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.

  3. #3
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335

    Re: Problem with CEvent

    thank you very much, for your help and corrections.

  4. #4
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    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.

  5. #5
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: Problem with CEvent

    Quote 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

  6. #6
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335

    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.

  7. #7
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Problem with CEvent

    Code:
    HANDLE Evento = NULL;
    should be

    Code:
    CEvent Evento;
    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.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured