Windows 8.1中的计时器 - 如何模拟Timer(TimerCallback)构造函数?

时间:2013-10-31 10:28:25

标签: c# timer windows-store-apps windows-8.1

我正在将一个使用System.Threading.Timer的现有.NET类库移植到面向Windows 8.1的Windows应用商店应用。 Timer类可用,但是相应的.NET Framework Timer似乎缺少一些选项。

特别是,Windows Store版本中只有两个构造函数可用:

public Timer(TimerCallback callback, Object state, int dueTime, int period);
public Timer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period);

.NET Framework包含此附加构造函数:

public Timer(TimerCallback callback);

根据MSDN documentation设置dueTimeperiod设置Timeout.Infinitestate设置Timer对象本身。

尝试替换单个参数构造函数,我“天真地”试图将Timer对象传递给Windows 8.1构造函数之一,如下所示:

Timer t;
t = new Timer(MyCallback, t, Timeout.Infinite, Timeout.Infinite);  // WILL NOT WORK!!!

但当然这只会产生编译错误

  

使用未分配的局部变量't'

State类中也没有SetState setter或Timer方法,因此构建后无法设置state

我可以做些什么来完全模仿完整框架的Timer(TimerCallback)构造函数?

2 个答案:

答案 0 :(得分:1)

请注意,只要您在设置字段/属性后手动启动计时器,这些选项都是可以接受的,这意味着您可以在适当的时间内使用Timeout.Infinite

州对象

将属性添加到状态对象:

public class MyState
{
   public Timer { get; set; }
}

//create empty state
MyState s = new MyState();
//create timer paused
Timer t = new Timer(MyCallback, s, Timeout.Infinite, Timeout.Infinite);
//update state
s.Timer = t;
//now safe to start timer
t.Change(..)

私人字段

_t = new Timer(MyCallback, null, Timeout.Infinite, Timeout.Infinite);

MyCallback(object state)
{
  // now have access to the timer _t
  _t.
}

内部阶级的私人领域

如果因为你想要启动和跟踪多个私有字段是不够的,那么创建一个包装计时器的新类。这可能是一个内部阶级:

public class ExistingClass
{
    public void Launch()
    {
        new TimerWrapper(this);
    }

    private sealed class TimerWrapper
    {
        private readonly ExistingClass _outer;
        private readonly Timer _t;

        public TimerWrapper(ExistingClass outer)
        {
            _outer = outer;
            //start timer
            _t = new Timer(state=>_outer.MyCallBack(this),
                           null, Timeout.Infinite, Timeout.Infinite);
        }

        public Timer Timer
        {
            get { return _t; }
        }
    }

    private void MyCallBack(TimerWrapper wrapper)
    {
        wrapper.Timer.
    }
}

答案 1 :(得分:1)

你可以使用一个闭包。例如:

Timer t = null;

t = new Timer(
    _ => 
    {
        if (t != null)
        {
            // simply use t here, for example
            var temp = t;
        }
    },
    null,
    Timeout.Infinite, 
    Timeout.Infinite);

注意我是如何测试t != null的,以防定时器在将回调分配给变量t之前已经调用了回调,如果您使用0作为值,则可能会发生这种情况。截至日期。使用Timeout.Infinite的值,这不可能真的发生,但我喜欢在多线程场景中保持防守。

除了t之外,您还可以在创建计时器时使用范围内的任何其他变量,因为它们都将被提升到闭包中(在回调中使用时)。

如果您只想要一个方法来替换丢失的构造函数,从而简化移植工作,那么它就是:

public static Timer Create(TimerCallback callback)
{
    Timer t = null;

    t = new Timer(_ => callback(t), null, Timeout.Infinite, Timeout.Infinite);

    return t;
}