首页 > 解决方案 > 如果我运行每分钟运行一次并从 App.Xaml.cs OnStart() 调用的异步方法,是否存在任何可能的性能问题?

问题描述

我有这段代码,我的意图是当应用程序打开时,它将PointChecker.CheckPoints();每分钟运行一个方法。

此方法与我的数据库同步运行更新db2.Execute("UPDATE ..... etc");

根据我的阅读理解:

https://xamarinhelp.com/xamarin-forms-async-task-startup/

有几种不同的方法可以实现这一点。

我想知道的是,运行这样的代码是否存在任何性能问题,如果我想以不同的方式运行它,这些问题可能会减少。特别是最近对 Xamarin.Forms 的工作方式(我的应用程序通过 Forms 在 iOS 和 Android 上运行)进行了任何更改,我应该考虑这些更改,这可能会导致执行此任务的更好方法。

    public App() {
        InitializeComponent();
        DB.PopulateTables();
        MainPage = new Japanese.MainPage();
    }

    protected override async void OnStart() {
        await Task.Run(() => {
            StartTimer();
        });
    }

    public void StartTimer() {
       if (!stopWatch.IsRunning)
          stopWatch.Start();
          Device.StartTimer(new TimeSpan(0, 0, 1), () => {
             if (stopWatch.IsRunning && stopWatch.Elapsed.Minutes >= 1) {
                PointChecker.CheckPoints();
                stopWatch.Restart();
             }
             return true;
          });
    }
    protected override void OnSleep() {
        stopWatch.Reset(); base.OnSleep();
    }
    protected override void OnResume() {
        base.OnResume(); stopWatch.Start();
    }

标签: xamarinxamarin.forms

解决方案


参考Async/Await - 异步编程的最佳实践

通过使用async void,您删除了代码捕获和处理可能由调用计时器引发的任何异常的能力。所以避免async void在除事件处理程序之外的任何东西上使用。

OnStart然而不是事件处理程序。只是根据文档的常规方法...

应用程序开发人员覆盖此方法以在应用程序启动时执行操作。

作为一种解决方法,您可以创建自己的自定义事件和处理程序,以允许async void在您的事件处理程序上执行。OnStart当被应用程序调用时,您将订阅该事件,然后引发要异步处理的自定义事件。

StartTimer不是一个繁重的方法,因此并不真正保证被异步调用。但是,它PointChecker.CheckPoints()被声明为对您的数据库同步调用。

此方法与我的数据库同步运行更新db2.Execute("UPDATE ..... etc");

然而,这可能会导致阻塞,这可能会在每次调用时影响性能。那应该是包含在异步调用中或重构为本机异步方法的方法。

//...

protected override void OnStart() {
    PointsChecking += OnPointsChecking; //subscribe to event
    StartTimer(); //start the timer as normal.
}

private event EventArgs PointsChecking = delegate { };

private async void OnPointsChecking(object sender, EventArgs args) {
    //asynchronously check points without blocking main thread
    await Task.Run(() => {
        PointChecker.CheckPoints();
        stopWatch.Restart();
    });
}

public void StartTimer() {
    if (!stopWatch.IsRunning)
        stopWatch.Start();
    Device.StartTimer(new TimeSpan(0, 0, 1), () => {
        if (stopWatch.IsRunning && stopWatch.Elapsed.Minutes >= 1) {
            PointsChecking(null, EventArgs.Empty); //invoked event
        }
        return true;
    });
}

//...

计时器将负责引发事件以处理重复操作。通过使事件处理程序异步,您可以避免阻塞主线程,并具有额外的优势,即能够捕获和处理调用的数据库操作引发的任何异常(如果需要)。


推荐阅读