2013-02-19 16 views
6

Buduję aplikację sklepu Windows przy użyciu C# i Xaml. Muszę odświeżyć dane po pewnym czasie (przynieść nowe dane z serwera). Kiedyś ThreadPoolTimer wykonywać moją funkcję odświeżania cyklicznie w następujący sposób:Wykonywanie funkcji okresowo po zakończeniu wykonywania funkcji

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); 

To działa prawidłowo. Jedynym problemem jest to, co jeśli funkcja odświeżania nie zostanie ukończona, zanim jej kolejna instancja zostanie przekazana do puli wątków. Czy jest jakiś sposób na określenie luki między jego wykonaniem.

Etap 1: załaduj Skrypt wykonywany funkcyjne (przyjmować dowolną ilość czasu)

Etap 2: Odśwież funkcja kończy wykonanie

Etap 3: GAP 15 min, a następnie przejść do punktu funkcję 1

odświeżania wykonuje. 15 minut po zakończeniu jego realizacji, wykonuje ponownie.

Odpowiedz

6

Ten problem rozwiąże AutoResetEvent. Zadeklaruj instancję klasy AutoResetEvent na poziomie klasy.

AutoResetEvent _refreshWaiter = new AutoResetEvent(true); 

Następnie wewnątrz kodu: 1. czekać na to, aż zostanie zasygnalizowany, a 2. przekazać swoje odniesienie jako argument do metody 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); 

Wreszcie, na końcu dp.RefreshAsync sposobu wywołać _refreshWaiter.Set(); tak, że jeżeli 15 sekund, a następnie przepuszcza następną RefreshAsync mogą być wykorzystane. Zauważ, że jeśli metoda RefreshAsync trwa mniej niż 15 minut, wykonanie przebiega normalnie.

4

myślę łatwiejszy sposób to zrobić z 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); 

To rozwiązanie zapewnia także Task, które mogą być stosowane do wykrywania błędów.

Powiązane problemy