SetTimer ohne Dialog



  • Hi

    Ich habe in einer Klasse, welche in einem anderen Thread ausgeführt wird einen Timer.

    Diser wird jedoch nur einmal ausgeführt (die Timerfunktion)
    Kann mir jemand sagen, wo das Problem liegt?

    Hier die Funktionsdefinition:

    TIMERPROC CheckCommunication(UINT nIDEvent)
    {
    return 0;
    }
    

    Hier der Timerstart:

    SetTimer (m_hWindow,1, 1000, CheckCommunication());
    


  • Mit den () rufst du die das eine mal auf. 😃



  • Ok habs geändert!
    Jetzt rufe ich es so auf:

    SetTimer (m_hWindow,1, 1000, CheckCommunication);
    

    Beim Kompilieren gibt es aber immer diesen Fehler:

    C:\Projekte\SJF\VDRoboter\Source\Cpp\Includes\Communication\Boardmanager.cpp(214): error C2664: 'SetTimer': Konvertierung des Parameters 4 von 'TIMERPROC (UINT)' in 'TIMERPROC' nicht möglich
    


  • so sieht ne richtige timer proc aus:

    VOID CALLBACK TimerProc(          HWND hwnd,
        UINT uMsg,
        UINT_PTR idEvent,
        DWORD dwTime
    );
    


  • TIMERPROC ist ein typedef für den Funktionstyp, der SetTimer übergeben wird.
    er sieht laut MSDN so aus:

    VOID CALLBACK TimerProc(          HWND hwnd,
        UINT uMsg,
        UINT_PTR idEvent,
        DWORD dwTime
    );
    

    Mach also sowas:

    VOID CALLBACK CheckCommunication(HWND hWnd, UINT uMsg, UINT_PTR event, DWORD dwTime)
    {
    AfxMessageBox("Blub");
    }
    


  • Funktioniert auch nicht!
    Ich habe hier nun mal die ganzen Funktionen:

    void CALLBACK CBoardmanager::CheckCommunication(HWND hWnd, UINT uMsg, UINT_PTR event, DWORD dwTime)
    {
    	CSingleLock singleLock(&m_CriticalSection);
    	CString szData1;
    	CString szData2;
    	CString szData3;
    	singleLock.Lock();
    	bool bOnReceive=m_bOnReceive;
    	singleLock.Unlock();
    	if(bOnReceive==false)
    	{
    		/************************************************************************/
    		/* Testsignal an Kontroller senden                                      */
    		/************************************************************************/
    		m_Kontroller1.SendData("2;t\r");
    	  //m_Kontroller2.SendData("3;t\r");
    		//m_Kontroller3.SendData("4;t\r");
    
    		/************************************************************************/
    		/* Verbindung prüfen (zeichen Empfangen von Antwort auf Testsignal      */
    		/************************************************************************/
    		szData1=m_Kontroller1.GetData();
    		//szData2=m_Kontroller2.GetData();
    		//szData3=m_Kontroller3.GetData();
    
    		/************************************************************************/
    		/* Kontrolle ob Verbindung Ok ist                                       */
    		/************************************************************************/
    		if(szData1=="" /*|| szData2=="" || szData3==""*/)
    		{
    			singleLock.Lock();
    			m_bRun=false;
    			singleLock.Unlock();
    			/************************************************************************/
    			/* Eintrag ins Journal                                                  */
    			/************************************************************************/
    			CJournal::WriteToJournal("Journal.csv","Error","Keine Verbindung mehr",ACP_CODEINFO);
    		}
    		else
    		{
    			/************************************************************************/
    			/* Kontrolle ob wirklick Testsignal erhalten                            */
    			/* Ansonsten werden empfangene Daten zwischengespeichert.								*/
    			/************************************************************************/
    			if(szData1!="2;t\r" && szData1!="")
    			{
    				if(szData1.Find("t")>0)
    				{
    					szData1=szData1.Left(szData1.Find("t")-2);
    				}
    				singleLock.Lock();
    				m_aszDataReceived.Add(szData1);
    				singleLock.Unlock();
    			}
    			if(szData2!="3;t\r" && szData2!="")
    			{
    				if(szData2.Find("t")>0)
    				{
    					szData2=szData2.Left(szData2.Find("t")-2);
    				}
    				singleLock.Lock();
    				m_aszDataReceived.Add(szData2);
    				singleLock.Unlock();				
    			}
    			if(szData3!="4;t\r" && szData3!="")
    			{
    				if(szData3.Find("t")>0)
    				{
    					szData3=szData3.Left(szData3.Find("t")-2);
    				}
    				singleLock.Lock();
    				m_aszDataReceived.Add(szData3);
    				singleLock.Unlock();			
    			}
    			DatenAufbereiten();
    		}
    	}
    }
    

    Und hier nochmals den Aufruf:

    SetTimer (m_hWindow,1, 1000, CheckCommunication);
    

    Dies gibt bei mir nun folgenden Fehler:

    C:\Projekte\SJF\VDRoboter\Source\Cpp\Includes\Communication\Boardmanager.cpp(213): error C2664: 'SetTimer': Konvertierung des Parameters 4 von 'void (HWND,UINT,UINT_PTR,DWORD)' in 'TIMERPROC' nicht möglich
    

    Was mache ich nun da falsch???



  • Du darfst die Funktion nicht als Memberfunktion einer Klasse deklarieren.



  • Hm, die MFC98 definiert die TimerProc als

    void CALLBACK EXPORT TimerProc(
       HWND hWnd,      // handle of CWnd that called SetTimer
       UINT nMsg,      // WM_TIMER
       UINT nIDEvent   // timer identification
       DWORD dwTime    // system time
    );
    

    mach also aus dem UINT_PTR (Parameter 3) ein UINT
    Hab mich irgendwie gewundert, warum da ein Zeiger anstatt dem Wert direkt übergeben wird.



  • Ich habe alle gemacht was vorgeschlagen wurde...
    Ich habe die Vermutung, dass der Rückgabetyp der Funktion nicht stimmt! (Laut der Meldung kann er die Rückgabe void nicht in TIMERPROC konvertieren)
    Die Callback funktion muss doch einen Wert zurückgeben oder nicht?

    C:\Projekte\SJF\VDRoboter\Source\Cpp\Includes\Communication\Boardmanager.cpp(212): error C2664: 'SetTimer': Konvertierung des Parameters 4 von 'void (void)' in 'TIMERPROC' nicht möglich
    

    Bes jetzt sieht diese ja so aus:

    void CALLBACK CheckSignal(HWND hWnd, UINT uMsg, UINT event, DWORD dwTime)
    {
    }
    

    Wenn ich aber eifach TIMERPROC als Rückgabetyp angebe, funzt es auch nicht!
    Was ist also noch falsch?



  • addict schrieb:

    C:\Projekte\SJF\VDRoboter\Source\Cpp\Includes\Communication\Boardmanager.cpp(212): error C2664: 'SetTimer': Konvertierung des Parameters 4 von 'void (void)' in 'TIMERPROC' nicht möglich
    

    Das stimmt auch nicht, du übergibst als Parameter 4 eine void (void) Funktion, es sollte aber eine void (HWND, UINT, UINT, DWORD) Funktion sein

    Folgendes funktioniert super:

    void CALLBACK CheckSignal(HWND hWnd, UINT uMsg, UINT event, DWORD dwTime) 
    { 
    	AfxMessageBox("OK");
    } 
    void CMyDlg::OnButton1() 
    {
    	SetTimer(0, 1000, CheckSignal);
    }
    


  • Ok jetzt läuft es hoffentlich...
    Habe aber nun ein anderes Problem!
    Ich habe ja die Funktion:

    void CALLBACK CheckSignal(HWND hWnd, UINT uMsg, UINT event, DWORD dwTime)
    {
    	CBoardmanager Manager;
    	Manager.CheckCommunication();
    }
    
    void CBoardmanager::CheckCommunication()
    

    Ich möchte nun die Funktion CheckCommunication() aufrufen ohne die Klasse CBoardmanager neu zu erstellen.
    Ich kann die Funktion CheckCommunication auch nicht static machen!
    Ist es irgendwie möglich eine Pointer auf die andere Klasse zu bekommen?
    Oder gibt es noch eine bessere Variante die Funktion ohne neue Klasseninitialisierung auszuführen?



  • Hm
    mir fallen mal spontan 3 Lösungwege ein

    1. eine globale Variable (in dem Fall ein globgales Objekt) anlegen, bzw. den Zeiger auf das Objekt global speichern
    2. Wenn dein Objekt in der App-Klasse (von CWinApp abgeleitet) ist, per AfxGetApp() einen Zeiger auf die App-Klasse erhalten und dann casten, z.B.
    void CALLBACK CheckSignal(HWND hWnd, UINT uMsg, UINT event, DWORD dwTime)
    {
        CMyApp *pApp; // Zeiger auf unsere App-Klasse
        pApp = (CMyApp*)AfxGetApp();
    
        CBoardmanager *pManager; // Zeiger auf die CBoardmanager Instanz
        pManager = &pApp->m_Manager; // m_Manager ist vom Typ CBoardmanager
        pManager->CheckCommunication();
    
        CBoardmanager Manager;
        Manager.CheckCommunication();
    }
    
    1. Ein Singleton verwenden.

    Grüße Rapha



  • die 2. Variante tönt nicht schlecht! Funktioniert dies auch, wenn die Klasse CBoardmanager in einem neuen Thread läuft?

    Was ist ein Singleton?



  • addict schrieb:

    die 2. Variante tönt nicht schlecht! Funktioniert dies auch, wenn die Klasse CBoardmanager in einem neuen Thread läuft?

    Jup, wobei du natürlich das Synchronisieren managen musst.

    addict schrieb:

    Was ist ein Singleton?

    Quasi eine Klasse, von der es immer nur eine Instanz geben kann.
    Bevor du ein Singleton verwendest, mach lieber ne globale Variable 🙂


Anmelden zum Antworten