C# 可移植类库中的定时器

C# 可移植类库中的定时器,c#,multithreading,timer,visual-studio-2013,portable-class-library,C#,Multithreading,Timer,Visual Studio 2013,Portable Class Library,我已经根据讨论创建了一个计时器类,但我有一个问题,经过的事件只发生一次。 较小的问题:如果不必在每次调用Start()时都实例化_计时器,这将是一件好事 使用系统; 使用系统线程; 使用System.Threading.Tasks; 使用System.Diagnostics.Contracts; 名称空间JellystonePark.Model { 内部委托无效TimerCallback(对象状态); 内部密封类计时器:CancellationTokenSource,IDisposable {

我已经根据讨论创建了一个计时器类,但我有一个问题,经过的事件只发生一次。 较小的问题:如果不必在每次调用Start()时都实例化_计时器,这将是一件好事

使用系统;
使用系统线程;
使用System.Threading.Tasks;
使用System.Diagnostics.Contracts;
名称空间JellystonePark.Model
{
内部委托无效TimerCallback(对象状态);
内部密封类计时器:CancellationTokenSource,IDisposable
{
内部计时器(TimerCallback回调、对象状态、TimeSpan dueTime、TimeSpan时段)
{
Assert(period==TimeSpan.frommilluses(-1),“此存根实现仅支持dueTime。”);
任务延迟(dueTime,Token).ContinueWith((t,s)=>
{
变量tuple=(tuple)s;
tuple.Item1(tuple.Item2);
},Tuple.Create(回调,状态),CancellationToken.None,
TaskContinuationOptions.Executes同步执行| TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
public new void Dispose(){base.Cancel();}
}
公共级PCLTimer
{
私人定时器;
专用时间间隔;
/// 
///信号之间的间隔(毫秒)。
/// 
公共双间隔
{
获取{return\u interval.totalmillizes;}
设置{u interval=TimeSpan.fromMillicles(值);Stop();Start();}
}
/// 
///如果PCLTimer正在运行,则为True,否则为false。
/// 
公共布尔启用
{
获取{returnnull!=\u timer;}
设置{if(value)Start();else Stop();}
}
/// 
///在指定的时间已过且PCLTimer已启用时发生。
/// 
公共事件事件处理程序;
/// 
///启动PCLTimer。
/// 
公开作废开始()
{
如果(0==\u间隔.总毫秒)
抛出新的InvalidOperationException(“在调用PCLTimer.Start()之前设置已用属性”);
_计时器=新计时器(失效、空、间隔、间隔);
}
/// 
///停止PCLTimer。
/// 
公共停车场()
{
_timer.Dispose();
}
/// 
///释放所有资源。
/// 
公共空间处置()
{
_timer.Dispose();
}
/// 
///调用经过的事件。
/// 
/// 
私有无效失效(对象状态)
{
如果(空!=\u计时器和空!=已过)
已过(此为EventArgs.Empty);
}
}
}

如果您对使用任务实现计时器感兴趣,可以尝试以下代码:

public delegate void TimerCallback(object state);

public sealed class Timer : CancellationTokenSource, IDisposable
{
    public Timer(TimerCallback callback, object state, int dueTime, int period)
    {
        Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
        {
            var tuple = (Tuple<TimerCallback, object>) s;

            while (true)
            {
                if (IsCancellationRequested)
                    break;
                Task.Run(() => tuple.Item1(tuple.Item2));
                await Task.Delay(period);
            }

        }, Tuple.Create(callback, state), CancellationToken.None,
            TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
            TaskScheduler.Default);
    }

    public new void Dispose() { base.Cancel(); }
}
public委托void TimerCallback(对象状态);
公共密封类计时器:CancellationTokenSource,IDisposable
{
公共计时器(TimerCallback回调、对象状态、int dueTime、int period)
{
Task.Delay(dueTime,Token).ContinueWith(异步(t,s)=>
{
变量tuple=(tuple)s;
while(true)
{
如果(已请求取消安装)
打破
Task.Run(()=>tuple.Item1(tuple.Item2));
等待任务。延迟(周期);
}
},Tuple.Create(回调,状态),CancellationToken.None,
TaskContinuationOptions.Executes同步执行| TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
public new void Dispose(){base.Cancel();}
}

如前所述,您可以在某些界面上引入依赖项,并要求用户为您提供特定的计时器实现。

我不清楚您要回答的实际问题是什么?您需要指定计时器多次启动的时间段。然后你会发现为什么这段代码很糟糕。@HansPassant你知道如何定义句点吗?我不想要一个完整的工作代码,只有一些指导,如何开始它。我必须在pcl库中实现一个计时器,我还没有找到任何有效的解决方案,如果你比这更好,请与我分享。任何应用程序使用你的库都不会给你提供计时器对象。编写ITimer和ITimerFactory接口。在(!IsCancellationRequested)
public delegate void TimerCallback(object state);

public sealed class Timer : CancellationTokenSource, IDisposable
{
    public Timer(TimerCallback callback, object state, int dueTime, int period)
    {
        Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
        {
            var tuple = (Tuple<TimerCallback, object>) s;

            while (true)
            {
                if (IsCancellationRequested)
                    break;
                Task.Run(() => tuple.Item1(tuple.Item2));
                await Task.Delay(period);
            }

        }, Tuple.Create(callback, state), CancellationToken.None,
            TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
            TaskScheduler.Default);
    }

    public new void Dispose() { base.Cancel(); }
}