2012-05-08 13 views
4

開始/停止/有効/無効の機能を提供するタイマークラスが必要で、NON UIである必要があります。メトロアプリ(.NET)の非UIタイマーの制御

私は2つのオプション

  1. DispatcherTimer見る - 定期タイマーオーバー>ノーコントロール - >は、それがUIスレッド

  2. ThreadPoolTimer上で実行されることを除いて、すべての機能を備えています。

私は、スレッドプールタイマーのラッパーを作成することを考えたが、それ以上なし/制限された制御のような非常に複雑なようでました。

指定されたscenearioのタイマークラスを設計する方法。 (私はSystem.Threading.Timerに似た何かを必要とします)。

答えて

4

MetroアプリケーションでUIが非常に反応的である必要があるため、DispatcherTimerを実行し、バックグラウンドスレッドで実行したいものに対してTask.Run()を呼び出すだけで十分です。

これはあなたのために動作しない場合 - これが場合参照してください。 DispatcherTimerと似たAPIを持つべきですが、別のスレッドで実行する必要があります。インターバルセットの期間を正確に待っているわけではないので、タイマーは非常に遅くなるでしょう。また、スレッドセーフではなく、私はそれを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

クール。 BTW - サンプルと一緒にWinRT XAML Toolkit(http://bit.ly/WinRTXamlToolkit)に追加し、間隔を幾分調整して、平均Tick周波数が間隔値に近い値になるようにしました。実際には、これらの調整がなくても、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タイマーのための資金が得られるかもしれません。

関連する問題