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