2012-05-08 41 views
4

我需要一個定時器類,它應該提供啓動/停止/啓用/禁用的功能,並且應該不是用戶界面。城域應用程序中受控制的非UI定時器(.NET)

我看到2個選項

  1. DispatcherTimer - >有不同之處在於它是在UI線程上執行

  2. ThreadPoolTimer所有功能 - >沒有超過週期定時器控制。

我想通過線程池計時器創建包裝,但似乎非常複雜,因爲沒有/有限的控制權。

如何爲所述場景設計一個計時器類。 (我需要類似於System.Threading.Timer的東西)。

回答

4

由於UI應該在Metro應用程序中響應速度很快 - 對於您希望在後臺線程上運行的內容,運行DispatcherTimer並調用Task.Run()可能就足夠了。

如果這不適合你 - 看看這是否。它應該有一個類似於DispatcherTimer的API,但在不同的線程上運行。並不是說它一直在等待Interval集合的持續時間,所以定時器將會出現嚴重遲到。它也不完全是線程安全的,我只用它玩了10分鐘,所以它可能不會工作,但由於它是開源的 - 你可以修改它以適應你的賬單。

public class BackgroundTimer 
{ 
    private AutoResetEvent _stopRequestEvent; 
    private AutoResetEvent _stoppedEvent; 

    #region Interval 
    private TimeSpan _interval; 
    public TimeSpan Interval 
    { 
     get 
     { 
      return _interval; 
     } 
     set 
     { 
      if (IsEnabled) 
      { 
       Stop(); 
       _interval = value; 
       Start(); 
      } 
      else 
      { 
       _interval = value; 
      } 
     } 
    } 
    #endregion 

    public event EventHandler<object> Tick; 

    #region IsEnabled 
    private bool _isEnabled; 
    public bool IsEnabled 
    { 
     get 
     { 
      return _isEnabled; 
     } 
     set 
     { 
      if (_isEnabled == value) 
       return; 

      if (value) 
       Start(); 
      else 
       Stop(); 
     } 
    } 
    #endregion 

    public BackgroundTimer() 
    { 
     _stopRequestEvent = new AutoResetEvent(false); 
     _stoppedEvent = new AutoResetEvent(false); 
    } 

    public void Start() 
    { 
     if (_isEnabled) 
     { 
      return; 
     } 

     _isEnabled = true; 
     _stopRequestEvent.Reset(); 
     Task.Run((Action)Run); 
    } 

    public void Stop() 
    { 
     if (!_isEnabled) 
     { 
      return; 
     } 

     _isEnabled = false; 
     _stopRequestEvent.Set(); 
     _stoppedEvent.WaitOne(); 
    } 

    private void Run() 
    { 
     while (_isEnabled) 
     { 
      _stopRequestEvent.WaitOne(_interval); 

      if (_isEnabled && 
       Tick != null) 
      { 
       Tick(this, null); 
      } 
     } 

     _stoppedEvent.Set(); 
    } 
} 
+0

感謝您的良好實施。 我會使用它,並在需要時進行更新。但大部分基礎工作已經完成。 線程安全/同步似乎是唯一關心的問題。 – Tilak

+1

很酷。順便說一句 - 我將它與示例一起添加到WinRT XAML Toolkit(http://bit.ly/WinRTXamlToolkit)中,並稍微調整了間隔,以便平均Tick頻率更接近Interval值所指示的值。即使沒有這些調整,它實際上似乎比DispatcherTimer更精確。 –

+0

存在WinRTXamlToolKit,我不知道。感謝分享,如果你有一些未決的項目/想法,我很樂意貢獻。 – Tilak

0

我能創造一個時鐘用下面的代碼:

ThreadPoolTimer Timer1 = ThreadPoolTimer.CreatePeriodicTimer(Timer1_ElapsedHandler, TimeSpan.FromSeconds(1)); 
clockTick = false; 
UpdateLoop(); 

爲此,您需要一個事件處理程序,在我的時鐘此設置計時器滴答:

public void Timer1_ElapsedHandler(ThreadPoolTimer timer) 
{ 
    clockTick = true; 
} 

然後更新GUI(或任何你需要的),有一個更新循環:

public async void UpdateLoop() 
{ 
    do 
    { 
     await Task.Delay(100); 
    } while (!clockTick); 
    ClockTextBlock.Text = DateTime.Now.ToString(); 
    clockTick = false; 
    UpdateLoop(); 
} 

大概將它包裝在一個類中並清理一下可能會爲您提供非UI定時器的基礎。

相關問題