2013-02-19 10 views
6

Sto costruendo un'app di Windows Store utilizzando C# e xaml. Ho bisogno di aggiornare i dati dopo un certo intervallo di tempo (portare i nuovi dati dal server). Ho usato ThreadPoolTimer di eseguire la mia funzione di aggiornamento periodicamente come segue:Eseguendo periodicamente una funzione dopo che la funzione ha completato il proprio compito

TimeSpan period = TimeSpan.FromMinutes(15); 
    ThreadPoolTimer PeriodicTimer =  ThreadPoolTimer.CreatePeriodicTimer(async(source)=> { 
    n++; 
    Debug.WriteLine("hello" + n); 
    await dp.RefreshAsync(); //Function to refresh the data 
    await Dispatcher.RunAsync(CoreDispatcherPriority.High, 
       () => 
       { 
        bv.Text = "timer thread" + n; 

       }); 

     }, period); 

Questo funziona correttamente. L'unico problema è che cosa succede se la funzione di aggiornamento non viene completata prima che la successiva istanza venga inoltrata al pool di thread. C'è un modo per specificare il divario tra la sua esecuzione.

Fase 1: Aggiornare esegue la funzione (prende qualsiasi quantità di tempo)

Fase 2: Aggiornare funzione completa la sua esecuzione

Fase 3: Gap per 15 minuti quindi andare al passo funzione 1

Refresh esegue. 15 minuti dopo la sua esecuzione, si esegue nuovamente.

risposta

6

Il AutoResetEvent risolverà questo problema. Dichiarare un'istanza AutoResetEvent di livello classe.

AutoResetEvent _refreshWaiter = new AutoResetEvent(true); 

poi dentro il tuo codice: 1. attesa su di esso fino a che non viene segnalato, e 2. passare il suo riferimento come argomento di metodo RefreshAsync.

TimeSpan period = TimeSpan.FromMinutes(15); 
    ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async(source)=> { 
    // 1. wait till signaled. execution will block here till _refreshWaiter.Set() is called. 
    _refreshWaiter.WaitOne(); 
    n++; 
    Debug.WriteLine("hello" + n); 
    // 2. pass _refreshWaiter reference as an argument 
    await dp.RefreshAsync(_refreshWaiter); //Function to refresh the data 
    await Dispatcher.RunAsync(CoreDispatcherPriority.High, 
       () => 
       { 
        bv.Text = "timer thread" + n; 

       }); 

     }, period); 

Infine, al termine della dp.RefreshAsync metodo, chiamare _refreshWaiter.Set(); modo che se 15 secondi sono passati poi il successivo RefreshAsync può essere chiamato. Notare che se il metodo RefreshAsync richiede meno di 15 minuti, l'esecuzione procede normalmente.

4

Penso che un modo più semplice per farlo è con async:

private async Task PeriodicallyRefreshDataAsync(TimeSpan period) 
{ 
    while (true) 
    { 
    n++; 
    Debug.WriteLine("hello" + n); 
    await dp.RefreshAsync(); //Function to refresh the data 
    bv.Text = "timer thread" + n; 
    await Task.Delay(period); 
    } 
} 

TimeSpan period = TimeSpan.FromMinutes(15); 
Task refreshTask = PeriodicallyRefreshDataAsync(period); 

Questa soluzione offre anche una Task che può essere utilizzato per rilevare gli errori.