metro app(.NET)中受控的非UI计时器

时间:2012-05-08 05:52:04

标签: .net timer windows-8 windows-runtime winrt-xaml

我需要一个计时器类,它应该提供启动/停止/启用/禁用的功能,并且应该是非UI。

我看到2个选项

  1. DispatcherTimer - >具有除在UI线程上执行的所有功能

  2. ThreadPoolTimer - >无法控制周期性计时器。

  3. 我正在考虑在线程池计时器上创建包装器,但似乎非常复杂,因为没有/有限的控制它。

    如何为指定的sceneario设计计时器类。 (我需要类似于System.Threading.Timer的东西。)

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分: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计时器的基金。