Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows 8.1中的计时器-如何模拟计时器(TimerCallback)构造函数?_C#_Timer_Windows Store Apps_Windows 8.1 - Fatal编程技术网

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

C# Windows 8.1中的计时器-如何模拟计时器(TimerCallback)构造函数?,c#,timer,windows-store-apps,windows-8.1,C#,Timer,Windows Store Apps,Windows 8.1,我正在将现有的.NET类库移植到针对Windows 8.1的Windows应用商店应用程序。Timer类可用,但与相应的.NET FrameworkTimer相关的一些选项似乎缺失 特别是,Windows应用商店版本中只有两个构造函数可用: public Timer(TimerCallback callback, Object state, int dueTime, int period); public Timer(TimerCallback callback, Object state, T

我正在将现有的.NET类库移植到针对Windows 8.1的Windows应用商店应用程序。
Timer
类可用,但与相应的.NET Framework
Timer
相关的一些选项似乎缺失

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

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);

根据设置
dueTime
period
Timeout.Infinite
state
计时器
对象本身

尝试替换单参数构造函数时,我“天真地”尝试将
计时器
对象传递到一个Windows 8.1构造函数中,如下所示:

Timer t;
t = new Timer(MyCallback, t, Timeout.Infinite, Timeout.Infinite);  // WILL NOT WORK!!!
当然,这只会产生编译错误

未赋值局部变量“t”的使用

Timer
类中也没有
State
setter或
SetState
方法,因此在构造后无法设置
状态


如何完全模拟完整框架的
计时器(TimerCallback)
构造函数?

请注意,只要在设置字段/属性后手动启动计时器,这些选项是可以接受的,这意味着在指定的时间内使用
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(..)
私人领域 内部类的私有域 如果一个私有字段不够,因为您想启动并跟踪多个字段,那么创建一个新类来包装一个计时器。这可能是一个内部类:

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

你可以使用闭包。例如:

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

due time参数中的
Timeout.Infinite
可防止出现该问题。i、 e.在计时器被后面的一行代码启动之前,回调不会被调用。我以前也尝试过这个方法,它不允许您使用闭包中可能没有ben赋值的值-它不会编译。@weston我在发布后不久就注意到了这两个问题。答案已经更新。“但我喜欢在多线程场景中防御”,您的代码所做的只是隐藏一个潜在的空引用异常。防御性编程不是确保程序不会抛出异常。如果它有一个执行特殊操作的
else
,或者抛出一个自定义异常,那就更好了。@weston我明白你的意思,但我不是这么想的。相反,我的想法是:如果回调的第一次迭代来得太早,只需什么都不做,等待第二次迭代。但是,正如您所看到的,当这个逻辑被很好地封装在一个方法中时,就不需要保护不可能发生的情况(因为Timeout.Infinite)。这个问题有点不对劲,Windows 8.1的相关性是什么。NET 4.5.1当然支持此构造函数。如果你真的在谈论一个商店应用程序,那么你根本不能使用这个类。计时器类在8.0中不存在,但它确实包含在8.1版本的Windows应用商店应用程序中。你只是在MSDN文档中看不到而已。@AndersGustafsson出于兴趣,你选择了哪个选项?承认这有点尴尬,但经过进一步调查,我发现移植代码的任何回调方法中都没有使用
state
。因此,我简单地将
计时器(回调)
构造函数替换为
计时器(回调,null,Timeout.Infinite,Timeout.Infinite)
。@AndersGustafsson lol至少是其他人编写的原始代码?在我的辩护中:是的,它是:-)
public static Timer Create(TimerCallback callback)
{
    Timer t = null;

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

    return t;
}