如果我运行每分钟运行一次并从App.Xaml.cs OnStart()调用的Async方法,是否会出现性能问题?

时间:2018-09-30 20:33:21

标签: xamarin xamarin.forms

我有这段代码,我的意图是当应用程序打开时,它将每分钟运行一个名为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();
    }

3 个答案:

答案 0 :(得分:3)

引用Async/Await - Best Practices in Asynchronous Programming

通过使用While (Get-BitsTransfer),可以消除代码捕获和处理计时器调用可能引发的异常的能力。因此,请避免在事件处理程序以外的任何东西上使用async void

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

  

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

作为解决方案,您可以创建自己的自定义事件和处理程序,以允许在事件处理程序上执行async void。当应用程序调用{​​{1}}时,您将预订事件,然后引发要异步处理的自定义事件。

async void并不是一个繁重的方法,因此并不能真正保证被异步调用。但是,OnStart被声明为针对您的数据库被同步调用。

  

此方法与StartTimer同步对我的数据库进行更新

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

PointChecker.CheckPoints()

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

答案 1 :(得分:3)

最近对Xamarin的更改不会影响到此。此方法是最有效的方法。我唯一要考虑的是为什么您的方法需要异步。您可以致电:

 protected override void OnStart()

another thread中,讨论了一种非UI阻塞的解决方案:

using Xamarin.Forms;
using System;
using System.Linq;
using System.Diagnostics;

namespace YourNamespace
{
    public partial class App : Application
    {
        private static Stopwatch stopWatch = new Stopwatch();
        private const int defaultTimespan = 1;

        protected override void OnStart()
        {
            // On start runs when your application launches from a closed state, 

            if (!StopWatch.IsRunning)
            {
                StopWatch.Start();
            }

            Device.StartTimer(new TimeSpan(0, 0, 1), () =>
            {
                // Logic for logging out if the device is inactive for a period of time.

                if (StopWatch.IsRunning && StopWatch.Elapsed.Minutes >= defaultTimespan)
                {
                    //prepare to perform your data pull here as we have hit the 1 minute mark   

                        // Perform your long running operations here.

                        InvokeOnMainThread(()=>{
                            // If you need to do anything with your UI, you need to wrap it in this.
                        });

                    stopwatch.Restart();
                }

                // Always return true as to keep our device timer running.
                return true;
            });
        }

        protected override void OnSleep()
        {
            // Ensure our stopwatch is reset so the elapsed time is 0.
            StopWatch.Reset();
        }

        protected override void OnResume()
        {
            // App enters the foreground so start our stopwatch again.
            StopWatch.Start();
        }
    }
}

最棒的是,这种方法是

  

不可知平台

答案 2 :(得分:-1)

我在相同的情况下可以在给定的时间间隔同步数据,因此我使用了android native service Sync Adapter。它基本上会执行什么操作,而不是在给定的间隔内管理呼叫,而是会移交给您的Android OS。我不知道在iOS上如何实现这一目标。

如果要实现同步适配器,请使用此Sample Code

我认为这是Android的最佳解决方案。