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 文档dueTimeperiodtoTimeout.InfinitestatetoTimer对象本身。

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

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

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

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

类中也没有State设置器或SetState方法Timer,因此state无法在构造后设置。

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

4

2 回答 2

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.
    }
}
于 2013-10-31T12:06:26.157 回答
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 作为dueTime 的值,可能会发生这种情况。使用 Timeout.Infinite 的值,这不可能真正发生,但我喜欢在多线程场景中采取防御措施。

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

如果您只想要一种方法来替换缺少的构造函数,从而减轻您的移植工作,这里是:

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

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

    return t;
}
于 2013-10-31T12:27:24.843 回答