2015-08-31 2 views
6

Quando uso System.Threading.Timer posso fermare la mia timer e farlo ripartire:Come posso cancellare da Device.StartTimer?

protected override void OnScrollChanged(int l, int t, int oldl, int oldt) 
{ 
    if (timer == null) 
    { 
     System.Threading.TimerCallback tcb = OnScrollFinished; 
     timer = new System.Threading.Timer(tcb, null, 700, System.Threading.Timeout.Infinite); 
    } 
    else 
    { 
     timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); 
     timer.Change(700, System.Threading.Timeout.Infinite); 
    } 
} 

Qual è il modo migliore per fermare Device.StartTimer e iniziare di nuovo?

+0

[Prova questo link] (http://solvedstack.com/questions/c-timer-or-thread-sleep) –

+0

È possibile utilizzare o Thread.Sleep oppure è possibile impostare nel costruttore il parametro periodo. –

+0

No, non riesco a dormire. L'applicazione deve funzionare – Kirill

risposta

7

Suppongo che si stia riferendo a Device.StartTime in XamarinForms. Il modo per fermare o continuare un'attività ricorrente è determinato da ciò che il secondo restituisce argomento:

// run task in 2 minutes 
Device.StartTimer(TimeSpan.FromMinutes(2),() => 
{ 
    if (needsToRecur) 
    { 
     // returning true will fire task again in 2 minutes. 
     return true; 
    } 

    // No longer need to recur. Stops firing task 
    return false; 
}); 

Se si vuole interrompere temporaneamente questo timer, e poi il fuoco nuovamente dopo qualche tempo, si dovrà chiamare Device.StartTimer di nuovo . Sarebbe bello avvolgerlo nella sua classe in cui è possibile utilizzare un membro privato per determinare se un'attività continua è ancora in esecuzione. Qualcosa di simile a questo:

public class DeviceTimer 
{ 
    readonly Action _Task; 
    readonly List<TaskWrapper> _Tasks = new List<TaskWrapper>(); 
    readonly TimeSpan _Interval; 
    public bool IsRecurring { get; } 
    public bool IsRunning => _Tasks.Any(t => t.IsRunning); 

    public DeviceTimer(Action task, TimeSpan interval, 
    bool isRecurring = false, bool start = false) 
    { 
    _Task = task; 
    _interval = interval; 
    IsRecurring = isRecurring; 
    if (start) 
     Start(); 
    } 

    public void Restart() 
    { 
    Stop(); 
    Start(); 
    } 

    public void Start() 
    { 
    if (IsRunning) 
     // Already Running 
     return; 

    var wrapper = new TaskWrapper(_Task, IsRecurring, true); 
    _Tasks.Add(wrapper); 

    Device.StartTimer(_interval, wrapper.RunTask); 
    } 

    public void Stop() 
    { 
    foreach (var task in _Tasks) 
     task.IsRunning = false; 
    _Tasks.Clear(); 
    } 


    class TaskWrapper 
    { 
    public bool IsRunning { get; set; } 
    bool _IsRecurring; 
    Action _Task; 
    public TaskWrapper(Action task, bool isRecurring, bool isRunning) 
    { 
     _Task = task; 
     _IsRecurring = isRecurring; 
     IsRunning = isRunning; 
    } 

    public bool RunTask() 
    { 
     if (IsRunning) 
     { 
     _Task(); 
     if (_IsRecurring) 
      return true; 
     } 

     // No longer need to recur. Stop 
     return IsRunning = false; 
    } 
    }   
} 
+0

problema che sto affrontando qui è se l'uso naviga anche in un'altra pagina, questo timer è attivo e continua a funzionare. La tua soluzione sembra promettente, ma chiedi quale azione/evento dovrebbe chiamare la funzione Stop() quando l'utente naviga dalla pagina. Se utilizzo l'azione OnDisappearing, viene attivato anche quando lo schermo è bloccato o l'app è in background. Non posso nemmeno usare l'evento premuto backbutton, perché non verrà attivato su androd se viene premuto il pulsante back del software. cosa ne pensi? – batmaci

+0

Ho aggiornato il codice con i risultati dell'esperimento. In caso di obiezioni, non esitate a disfare. – Shimmy