Newsgroup: it.comp.programmare.win32
Titolo: Timer

Salve a tutti
lavoro con le MFC e oggi ho riscontrato un problemino
Mi serve un Timer di 42millisecondi
Implementando sulla View
e facendo un paio di stampe, noto che in in 10sec
dovrebbe scattare 238 volte invece impiega circa 12 sec.
Perchč?
C'č un limite sotto Windows?
Ho provato anche a creare un Thread derivato da CWinThread e ricevere il msg
WM_TIMER
su questo Thread di interfaccia... ma niente.
Come posso risolvere il problema?
Grazie
Roberto

 Perchè?
WM_TIMER è un messaggio a bassa priorità, questo significa che viene 
inviato quando il sistema non ha niente di meglio da fare (in parole 
povere). Ma a prescindere da questo, 42 ms mi sembra (correggetemi se 
sbaglio) un tempo troppo vicino alla risoluzione, per cui un errore del 20% 
ci sta pure.

 Mi serve un Timer di 42millisecondi
[cut]
il timer normale non fa per te
usa gli hoght definition timer:QueryPerformanceCounter,
QueryPerformanceFrequency
ciao

 Come posso risolvere il problema?
non usando WM_TIMER
-- 
  < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
      Don't stand, REACT!      version 0.1.2. C, C++ and ASM developers
                               and beta testers are welcome!

 ha scritto nel messaggio
news:Xns93E6D8B2...@127.0.0.1...


 ha scritto nel
messaggio news:NmN3b.18566$d66.4...@news2.tin.it...


 Grazie
ciao

 ha scritto nel
messaggio news:pr%3b.1415$nw1....@news1.tin.it...

Non è per l'ultilizzo, ho visto su MSDN e mi sembra chiaro,
ma quello che nn riesco a capire è dove e come devo usarle
queste funzioni...
Grazie


Potresti mettere il thread in attesa su un evento col timeout che ti serve.
Prima di tornare allo stato di attesa ricalcoli il tempo necessario e lo
rimetti come timeout.
Se ti è sufficiente il GetTickCount() sei a posto, altrimenti potresti usare
il multimedia timer o l'high resolution timer.

 dovrebbe scattare 238 volte invece impiega circa 12 sec.
Giusto, anche se dovrebbe impiegarne circa 13 di secondi per
scattare 238 volte. Il problema sta nel fatto che con
semplici timer non puoi ottenere un intervallo inferiore a
55ms. (anche se setti di meno). Per valori inferiori e timer
più precisi, passa ai timer multimediali (trovi ovviamente
tutte le informazioni su MSDN, "Multimedia Timer
Functions").
==========================
Stefano Frosio
http://www.esse-effe.com
==========================


Sempre + di 10 secondi impiega...
Ti invio il codice
// ThreadView.cpp : implementation of the CThreadView class
//
#include "stdafx.h"
#include "Thread.h"
#include "ThreadDoc.h"
#include "ThreadView.h"
#include "afxmt.h"
CEvent threadStart;
CEvent threadEnd;
const WM_SEND = WM_USER + 100;
const WM_THREADENDED = WM_USER + 101;
UINT ThreadProc(LPVOID param);
////////////////////////////////////////////////////////////////////////////
/
// CThreadView
IMPLEMENT_DYNCREATE(CThreadView, CView)
BEGIN_MESSAGE_MAP(CThreadView, CView)
 //{{AFX_MSG_MAP(CThreadView)
 ON_MESSAGE(WM_THREADENDED, OnThreadended )
 ON_MESSAGE(WM_SEND, OnSend )
 ON_WM_CREATE()
 ON_COMMAND(ID_THREAD_START, OnThreadStart)
 ON_COMMAND(ID_THREAD_STOP, OnThreadStop)
 //}}AFX_MSG_MAP
 // Standard printing commands
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////
/
// CThreadView construction/destruction
CThreadView::CThreadView()
{
 m_Curr = 0;
}
////////////////////////////////////////////////////////////////////////////
/
// CThreadView message handlers
UINT ThreadProc(LPVOID param)
{
 ::WaitForSingleObject( threadStart.m_hObject, INFINITE );
 ::MessageBox( (HWND)param, "Thread Attivo.", "Thread", MB_OK );
 BOOL keepRunning = TRUE;
 while( keepRunning )
 {
  int result = ::WaitForSingleObject( threadEnd.m_hObject, 42 );
  if( result == WAIT_OBJECT_0 )
   keepRunning = FALSE;
  else if( result == WAIT_TIMEOUT )
   ::PostMessage( (HWND)param, WM_SEND, 0, 0 );
 }
 ::PostMessage( (HWND)param, WM_THREADENDED, 0, 0 );
 return 0;
}
int CThreadView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
 HWND hwnd = GetSafeHwnd();
 m_pTh = AfxBeginThread( ThreadProc, hwnd );
 return 0;
}
void CThreadView::OnThreadStart()
{
 threadStart.SetEvent();
}
void CThreadView::OnThreadStop()
{
 threadEnd.SetEvent();
}
LONG CThreadView::OnThreadended(WPARAM wPAram, LPARAM lParam)
{
 AfxMessageBox( "Thread Stop" );
 return 1L;
}
LONG CThreadView::OnSend(WPARAM wPAram, LPARAM lParam)
{
 CTime t;
 m_Curr %= 238;
 if( m_Curr == 0 )
 {
  t = CTime::GetCurrentTime();
  TRACE( "%d = %d:%d\n", m_Curr, t.GetMinute(), t.GetSecond() );
 }
 m_Curr++;
 return 1L;
}
Ciao
JoGiò

 e cosa allora?
inventati un messaggio WM_USER + qualcosa che la finestra gestisca come 
gestisci WM_TIMER adesso, e spediscilo da un altro thread


 Grazie
Come da MSDN:
The QueryPerformanceCounter function retrieves the current value of the
high-resolution performance counter (if one exists on the system). By
calling this function at the beginning and end of a section of code, an
application essentially uses the counter as a high-resolution timer. For
example, suppose that QueryPerformanceFrequency indicates that the
frequency of the high-resolution performance counter is 50,000 counts per
second. If the application calls QueryPerformanceCounter immediately
before and immediately after the section of code to be timed, the counter
values might be 1500 counts and 3500 counts, respectively. These values
would indicate that .04 seconds (2000 counts) elapsed while the code
executed. 
 
A me sembra tutto chiarissimo, no?
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 A me sembra tutto chiarissimo, no?
la cosa che non ti dicono e' di non usarlo in programmi che girano 40 giorni
(o meglio se lo usi pesantemente crearti un roll down del valore a fine
scala) perche' il QPC dopo una 40 di giorni di exec time si resetta e
ripparte da 0 ... e se tu fai un confronto con il valore salvato magari
qualche attimo prima di uscire dalla scala ottieni un valore negativo e
sballato, al posto della vera differenza dei tempi ...
quindi bisognerebbe sempre inserire :
val = QPC();
if (prec_val > val) prec_val - MAX_QPC_VALUE;
delta = abs(val - prec_val);
prec_val = val;
l'unico modo per rimanere sempre con il delta di differenza positivo e
corretto.
ciao
ps: cmq questo codice non tiene conto di una particolare situazione in cui
puo' avvenire il superamento del valore attuale al valore precedente, ma
capita solo in un'occasione eccezionale in cui si chiede il QPC solo dopo i
40 giorni (e penso sia assurda come cosa, ma possibile, in quel caso
bisognerebbe salvarsi anche il sistem tyme ed usarlo come metro di confronto
grossolano per sapere quando e' successo questa particolare situazione)


Sicuramente sarai piů bravo di me!!!
Come ho detto nei messaggi precedenti per quanto riguarda le funzioni nn ci
sono problemi,
č per l'architettura sw che sto trovando problemi
Cioč mi serve che una funzione venga chiamata circa 240 volte in 10 secondi
un timer di 42ms.
Tutto qui
Grazie


Scusa se rispondo adesso ma ho sempre troppo da fare :-)
Se non sbagliio ti avevo detto di ricalcolare il successivo timeout.
Quindi non dovresti porlo fisso a 42 msec ma di verificare quanto tempo è
trascorso dal precedente timeout e sottrarre quel valore dal tuo tempo fisso


Grazie per il tempo che mi dedichi
ma ho risolto...
Non inserisco il timeout nella chiamata ::WaitFor....(event, timeout)
ma ho usato le funzioni QueryPerformanceCounter e ...Frequency
se il tempo trascorso (nel while for ever del  thread ) č maggiore del
timeout
allora scatta  la mia funzione
poi con una ::PeekMessage riesco anche a controllare il thread della mia
applicazione
Grazie
JoGiň