2013-02-19 38 views
6

Tôi đang xây dựng một ứng dụng cửa sổ cửa sổ bằng C# và xaml. Tôi cần phải làm mới dữ liệu sau một khoảng thời gian nhất định (mang dữ liệu mới từ máy chủ). Tôi đã sử dụng ThreadPoolTimer để thực thi chức năng làm mới của tôi định kỳ như sau:Thực thi chức năng định kỳ sau khi chức năng hoàn thành nhiệm vụ

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

Điều này hoạt động bình thường. Vấn đề duy nhất là nếu chức năng refresh không hoàn thành trước khi thể hiện kế tiếp của nó được gửi tới pool thread. Có cách nào để xác định khoảng cách giữa thực thi của nó.

Bước 1: Làm mới chức năng thực thi (mất bất kỳ số lượng thời gian)

Bước 2: Làm mới chức năng hoàn thành thực hiện của nó

Bước 3: Gap cho 15mins sau đó đi đến Bước chức năng 1

Refresh thực hiện. 15 phút sau khi thực thi kết thúc, nó thực thi lại.

Trả lời

6

AutoResetEvent sẽ giải quyết vấn đề này. Khai báo một cá thể AutoResetEvent cấp lớp.

AutoResetEvent _refreshWaiter = new AutoResetEvent(true); 

Sau đó, trong mã của bạn: 1. đợi cho đến khi nó được báo hiệu và 2. chuyển tham chiếu của nó làm đối số cho phương thức 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); 

Cuối cùng, vào cuối dp.RefreshAsync phương pháp, gọi _refreshWaiter.Set(); để nếu 15 giây đã trôi qua thì RefreshAsync tiếp theo có thể được gọi. Lưu ý rằng nếu phương thức RefreshAsync mất ít hơn 15 phút, quá trình thực thi sẽ diễn ra như bình thường.

4

Tôi nghĩ một cách dễ dàng hơn để làm điều này là với 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); 

Giải pháp này cũng cung cấp một Task mà có thể được sử dụng để phát hiện lỗi.

Các vấn đề liên quan