PCL .NET 4.5计时器

10
我正在使用Xamarin和MvvmCross构建跨平台应用程序。我需要每分钟调用服务器以进行更新(稍后我将转向推送通知),但我无法在我的核心项目中创建计时器。我看过MvvmCross N+42,但我认为目标项目较旧,允许计时器。下面是我的目标框架。
有没有更好的方法让我不断调用调用服务的方法?
  • .NET Framework 4.5及更高版本
  • Windows Store应用(Windows 8)及更高版本
  • Windows Phone 8
  • Xamarin.Android
  • Xamarin.iOS

这可能与您有关:https://dev59.com/gGcs5IYBdhLWcg3w0HOz - Jason
谢谢,我看过那个帖子,但由于Xamarin的原因,我无法针对Windows 8.1及以上版本进行目标定位。 - user1049099
没错,但在提及8.1的永久修复之前,建议采用一些解决方法。至少我是这么理解的。 - Jason
我尝试了一些方法,创建了一个.NET 4.0 PCL并在其中创建计时器实例,但它们似乎会导致我的应用程序崩溃。我不知道这是因为我正在使用带有MVVMCross的Xamarin还是其他原因。 - user1049099
1
我犯了一个大错误,没有引用项目,这是一个很糟糕的错误。 - user1049099
2个回答

9

@stevemorgan的回答非常好。我根据那段代码创建了一个计时器工具,使它更易重用。我还添加了一个“runOnce”参数,它将在第一次滴答后停止计时器。

public class PclTimer
{
    public bool IsRunning { get; private set; }

    public TimeSpan Interval { get; set; }
    public Action Tick { get; set; }
    public bool RunOnce { get; set; }
    public Action Stopped { get; set; }
    public Action Started { get; set; }

    public PclTimer(TimeSpan interval, Action tick = null, bool runOnce = false)
    {
        Interval = interval;
        Tick = tick;
        RunOnce = runOnce;
    }

    public PclTimer Start()
    {
        if (!IsRunning)
        {
            IsRunning = true;
            Started?.Invoke();
            var t = RunTimer();
        }

        return this;
    }

    public void Stop()
    {
        IsRunning = false;
        Stopped?.Invoke();
    }

    private async Task RunTimer()
    {
        while (IsRunning)
        {
            await Task.Delay(Interval);

            if (IsRunning)
            {
                Tick?.Invoke();

                if (RunOnce)
                {
                    Stop();
                }
            }
        }
    }
}

我在MvvmCross中使用这个功能,没有任何问题:
timer = new Timer(TimeSpan.FromSeconds(4), 
            () => ShowViewModel<UserMatchViewModel>(), true)
            .Start();

3

由于异步/等待的奇妙之处,您始终可以自己完成它:

public async Task RunTimer()
{
    while(_timerRunning)
    {
        // Do Work
        // ...

        await Task.Delay(_timerInterval);
    }
}

当你调用它时,不要使用 await。它将在后台线程上运行,并且您可以通过从其他地方设置 _timerRunning 字段(或通过杀死从调用返回的任务)来终止循环。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接