2011-05-25 9 views
7

Come si modifica l'intervallo in System.Threading.Timer dalla funzione di richiamata di questo timer? È corretto?Come si modifica l'intervallo di tempo in System.Threading.Timer dalla funzione di richiamata di questo timer?

Fare così. Non è successo.

public class TestTimer 
{ 
    private static Timer _timer = new Timer(TimerCallBack); 

    public void Run() 
    { 
     _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(1)); 
    } 

    private static void TimerCallBack(object obj) 
    { 
     if(true) 
      _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10)); 
    } 

} 
+2

se (vero) ??? ......... –

+1

@Mitch Wheat, che è valido per qualche buona ragione, testare ad esempio? – crypted

+1

Mitch, è solo un esempio. Non portarlo al cuore. lol – mrbrooks

risposta

8

Questa linea genera una ricorsione infinita:

if(true) 
    _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10)); 

Le prime forze parametri TimerCallBack per eseguire subito. Quindi lo esegue ancora e ancora indefinitamente.

La correzione sarebbe

if(true) 
    _timer.Change(TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); 
+0

Grazie mille! – mrbrooks

4

Il problema è che la chiamata a Change specifica che il prossimo chiamata dovrebbe accadere immediatamente. Se hai intenzione di chiamare Changeogni ora, puoi semplicemente usare un periodo di Timeout.Infinite (che è solo una costante di -1) per dirgli di evitare di ripetere il tutto dopo la prossima volta - ma continuerà comunque a sparare , perché la prossima volta lo resetti. Ad esempio:

using System; 
using System.Threading; 

static class Program 
{ 
    private static Timer timer = new Timer(TimerCallBack); 

    public static void Main() 
    { 
     timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1)); 
     Thread.Sleep(10000); 

    } 

    private static void TimerCallBack(object obj) 
    { 
     Console.WriteLine("{0}: Fired", DateTime.Now); 
     timer.Change(TimeSpan.FromSeconds(3), 
        TimeSpan.FromMilliseconds(Timeout.Infinite)); 
    } 
} 

In alternativa, si potrebbe cambiare solo una volta, e poi lasciarlo:

using System; 
using System.Threading; 

static class Program 
{ 
    private static Timer timer = new Timer(TimerCallBack); 
    private static bool changed = false; 

    public static void Main() 
    { 
     timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1)); 
     Thread.Sleep(10000); 

    } 

    private static void TimerCallBack(object obj) 
    { 
     Console.WriteLine("{0}: Fired", DateTime.Now); 
     if (!changed) 
     { 
      changed = true; 
      TimeSpan interval = TimeSpan.FromSeconds(3); 
      timer.Change(interval, interval); 
     } 
    } 
} 

Nota che nulla sta utilizzando l'intervallo iniziale (1 secondo nei campioni sopra) in entrambi i casi , perché stiamo chiamando immediatamente Change - se vuoi davvero un orario diverso prima della prima chiamata, non utilizzare TimeSpan.Zero nella chiamata iniziale a Change.

+0

Grazie mille! – mrbrooks

+0

Solo per la cronaca, mentre ovviamente puoi usare -1 per "Infinito", i documenti dicono che puoi usare 'Timeout.Infinite', che penso mostri più chiaramente l'intenzione. ;) –

+0

@JamesWilkins: True Will edit. (Anche se 'Timeout.Infinite' fosse un' TimeSpan' sarebbe più chiaro - i documenti per 'Timer.Change (int, int)' menzionano 'Timeout.Infinite'; i documenti per' Timer.Change (TimeSpan, TimeSpaan) 'Non :( –

Problemi correlati