4

開始/停止/有効化/無効化する機能を提供し、非 UI であるタイマー クラスが必要です。

2つのオプションが表示されます

  1. DispatcherTimer -> UI スレッドで実行されることを除いて、すべての機能を備えています

  2. ThreadPoolTimer -> 定期的なタイマーを制御できません。

スレッドプール タイマーのラッパーを作成することを考えていましたが、それに対する制御がない/制限されているため、非常に複雑に思えます。

指定されたシナリオのタイマー クラスを設計する方法。(System.Threading.Timer に似たものが必要です)。

4

2 に答える 2

4

UI は Metro アプリで非常に応答性が高い必要があるため、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();
    }
}
于 2012-05-08T06:41:16.887 に答える
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 タイマーの基礎が得られるかもしれません。

于 2012-10-01T23:05:21.007 に答える