简体   繁体   English

Windows 8.1中的Timer-如何模仿Timer(TimerCallback)构造函数?

[英]Timer in Windows 8.1 - how to mimic Timer(TimerCallback) constructor?

I am porting an existing .NET class library that uses System.Threading.Timer to a Windows Store app that targets Windows 8.1. 我要将使用System.Threading.Timer的现有.NET类库移植到面向Windows 8.1的Windows应用商店应用中。 The Timer class is available, but a few options seem to be missing in relation to the corresponding .NET Framework Timer . Timer类可用,但是相对于相应的.NET Framework Timer似乎缺少一些选项。

In particular, there are only two constructors available in the Windows Store version: 特别是,Windows Store版本中只有两个构造函数可用:

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

.NET Framework contains this additional constructor: .NET Framework包含以下附加构造函数:

public Timer(TimerCallback callback);

which according to the MSDN documentation sets dueTime and period to Timeout.Infinite and state to the Timer object itself. 根据MSDN文档,其dueTimeperiodTimeout.Infinite并将state设置为Timer对象本身。

Trying to replace the single argument constructor, I have "naively" tried to pass the Timer object into one of the Windows 8.1 constructors, like this: 试图替换单个参数构造函数,我已经“天真”地尝试将Timer对象传递给Windows 8.1构造函数之一,如下所示:

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

but of course this only yields the compilation error 但是当然这只会产生编译错误

Use of unassigned local variable 't' 使用未分配的局部变量“ t”

There is also no State setter or SetState method in the Timer class, so the state cannot be set after construction. Timer类中也没有State setter或SetState方法,因此无法在构造后设置state

What can I do to fully mimic the full framework's Timer(TimerCallback) constructor? 我应该怎么做才能完全模仿整个框架的Timer(TimerCallback)构造函数?

Note that these options are acceptable as long as you start the timer manually after the field/property is set, which means using Timeout.Infinite for due time which you are. 请注意,只要您在设置字段/属性后手动启动计时器,这些选项就可以接受,这意味着您可以在适当的时间使用Timeout.Infinite

State Object 状态对象

Add a property to a state object: 向状态对象添加属性:

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(..)

Private Field 私人领域

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

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

Private Field of an Inner Class 内部班级的私人领域

And if one private field is not enough because you want to launch and track multiple, make a new class that wraps a timer. 如果一个私有字段还不够,因为您要启动和跟踪多个私有字段,请创建一个包装计时器的新类。 This could be an inner class: 这可能是一个内部类:

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.
    }
}

You can use a closure. 您可以使用闭包。 For example: 例如:

Timer t = null;

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

Notice how I test that t != null , just in case the timer already calls the callback before it has been assigned to the variable t , which might happen if you were to use 0 as a value for dueTime. 请注意,我是如何测试t != null ,以防万一计时器已在将回调分配给变量t之前调用了该回调,如果您将0用作DueTime的值,则可能会发生这种情况。 With a value of Timeout.Infinite, that can't really happen, but I like being defensive in multithreaded scenarios. 有了Timeout.Infinite的值,这实际上不可能发生,但是我喜欢在多线程方案中采取防御措施。

In addition to t , you can use any other variable that is in scope when the timer is created, as they will all be lifted into the closure (when used in the callback). 除了t ,您还可以使用创建计时器时范围内的任何其他变量,因为它们都将被提升到闭包中(在回调中使用时)。

If you only want a method to replace the missing constructor, easing your porting effort, here it is: 如果您只想使用一种方法来替换缺少的构造函数,从而简化了移植工作,则这里是:

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

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

    return t;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM