Comment puis-je lancer une méthode en arrière-plan sur mon application Xamarin?

une Fois que l'application est ouvrir et en cours d'exécution je voudrais un processus de fond pour vérifier une base de données et pour faire une mise à jour en fonction des données dans la base de données. Je voudrais faire cette vérification chaque minute. Je veux seulement que cela arrive lorsque l'application est au premier plan, en vue de l'utilisateur.

Quelqu'un peut-il me donner des suggestions sur la façon dont je fais cela? Je suppose que je peux appeler une méthode d'ici, mais je ne sais pas comment faire. Aussi je ne sais pas comment arrêter ou même si je dois annuler / arrêter manuellement le processus. Serait-il annuler lui-même lorsque l'application est en arrière-plan et de redémarrer lorsque l'application est revenue au premier plan?

public partial class App : Application
{

   protected override void OnStart()
   {
      App.DB.InitData();
      MainPage = new Japanese.MainPage();
   }

Mais je dois faire cette course sur un thread différent et si oui, comment pourrais-je le faire.

Désolé si ma question n'est pas claire. S'il vous plaît demandez et je peux mettre à jour si cela n'a pas de sens.

24
demandé sur Alan2 2017-07-20 11:47:27

7 réponses

ce que nous avons fait dans notre demande de formulaires était de faire usage de L'appareil.Minuteur et Chronomètre classe disponible dans le Système.Diagnostic, et de la Xamarine.Des formes pour créer un minuteur managé très générique avec lequel nous pourrions interagir en utilisant les méthodes onStart, onSleep et onResume dans Xamarin.Forme.

Cette solution particulière ne nécessite pas de logique spécifique à la plate-forme, et le chronomètre et le chronomètre de l'appareil ne sont pas des interfaces utilisateur. blocage.

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();
        }
    }
}



Edit:

Pour donner un contexte à la façon dont la solution ci-dessus fonctionne étape par étape:

l'application démarre à partir d'un état fermé et la méthode 'OnStart()' crée notre périphérique.La minuterie qui cogne à chaque seconde. Il démarre également notre chronomètre qui compte jusqu'à une minute.

lorsque l'application passe à l'arrière-plan, la méthode "OnSleep" est activée à ce point si nous devions passer un "false" valeur dans notre Dispositif.StartTimer() de l'action, cela n'allait pas commencer de nouveau. Ainsi, nous avons simplement réinitialiser notre chronomètre prêt pour quand l'application est à nouveau ouverte.

quand l'application revient au premier plan, elle frappe la méthode "OnResume", qui démarre simplement le chronomètre existant.

2018 Edit:

cette réponse a encore quelques mérites même en 2018, mais surtout pour des situations très spécifiques. Il y a une meilleure plateforme des façons spécifiques de répliquer cette fonctionnalité même en Xamarin.Forme. Ce qui précède reste encore un moyen agnostique de plate-forme pour effectuer une tâche après un certain temps, en tenant compte de l'activité/l'inactivité de l'utilisateur.

8
répondu Digitalsa1nt 2018-07-24 20:25:12

vous pouvez utiliser ceci,

 System.Threading.Tasks.Task.Run(() =>
 {
      //Add your code here.
 }).ConfigureAwait(false);
17
répondu Manish Sharma 2018-02-26 11:28:21

pour exécuter une tâche de fond utilisez un Service. En général, les tâches sont classées soit comme des tâches de longue durée, soit comme des tâches périodiques.

le code pour le service sous android ressemble à ceci

[Service]
public class PeriodicService : Service
{ 
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        // From shared code or in your PCL


        return StartCommandResult.NotSticky;
    }
}

Et pour invoquer le service en arrière-plan

   var intent = new Intent (this, typeof(PeriodicService));
   StartService(intent);

Dans le cas où veut appeler et vérifier après chaque minute

private void StartBackgroundDataRefreshService ()
{
    var pt = new PeriodicTask.Builder ()
        .SetPeriod (1800) // in seconds; minimum is 30 seconds
        .SetService (Java.Lang.Class.FromType (typeof(BackgroundService)))
        .SetRequiredNetwork (0)
        .SetTag (your package name) // package name
        .Build ();

        GcmNetworkManager.GetInstance (this).Schedule (pt);
}

pour savoir quel type de service est bon de vous lire ce tutoriel Types de Services

Xamarin Blog périodique de service d'arrière-plan Xamarin Blog

L'autre exemple est

public class PeriodicService : Service
{ 
 private static Timer timer = new Timer();     
  public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
        return StartCommandResult.NotSticky;
    }

   private class mainTask extends TimerTask
    { 
        public void run() 
        {
         //your code
        }
    } 
}

voici un exemple de Code de Xamarin Android Service qui effectuera la tâche après toutes les 10 Secondes

using System;
using System.Threading;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;

namespace SimpleService
{

[Service]
public class SimpleStartedService : Service
{
    static readonly string TAG = "X:" + typeof(SimpleStartedService).Name;
    static readonly int TimerWait = 10000;
    Timer timer;
    DateTime startTime;
    bool isStarted = false;

    public override void OnCreate()
    {
        base.OnCreate();
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug(TAG, $"OnStartCommand called at {startTime}, flags={flags}, startid={startId}");
        if (isStarted)
        {
            TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
            Log.Debug(TAG, $"This service was already started, it's been running for {runtime:c}.");
        }
        else
        {
            startTime = DateTime.UtcNow;
            Log.Debug(TAG, $"Starting the service, at {startTime}.");
            timer = new Timer(HandleTimerCallback, startTime, 0, TimerWait);
            isStarted = true;
        }
        return StartCommandResult.NotSticky;
    }

    public override IBinder OnBind(Intent intent)
    {
        // This is a started service, not a bound service, so we just return null.
        return null;
    }


    public override void OnDestroy()
    {
        timer.Dispose();
        timer = null;
        isStarted = false;

        TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
        Log.Debug(TAG, $"Simple Service destroyed at {DateTime.UtcNow} after running for {runtime:c}.");
        base.OnDestroy();
    }

    void HandleTimerCallback(object state)
    {
        TimeSpan runTime = DateTime.UtcNow.Subtract(startTime);
        Log.Debug(TAG, $"This service has been running for {runTime:c} (since ${state})." );
    }
}

}

8
répondu Ramankingdom 2017-07-28 03:21:31

il y a plusieurs façons de faire cela dans iOS et Android. Dans les formes de Xamarin la plupart de cette fonctionnalité tombe sous le nom de semi-finition. Il y a beaucoup de tutoriels. Celui-ci est assez élaboré et mérite certainement d'être vérifié:

http://arteksoftware.com/backgrounding-with-xamarin-forms/

Dans Android une grande partie de ce travail est effectué dans un Service D'Arrière-Plan. Pour iOS regarder dans Long Cours d'exécution ou Longueur Finie Tâches. Comme vous pouvez le voir à partir de cela, il n'y a pas de Xamarin forme manière de le faire. Vous aurez besoin d'écrire Xamarin.Androïde et Xamarin.code iOS spécifique.

7
répondu Steven Thewissen 2017-07-20 09:07:15

Vous pouvez utiliser

Device.StartTimer(TimeSpan.FromMinutes(1), () =>
{
   var shouldTimerContinueWork = true;
   /*your code*/
   return shouldTimerContinueWork;
});

cette minuterie fonctionne sur le thread d'arrière-plan, utilise des appareils horloge et entrée sûre.

Pour arrêter le minuteur lorsque l'application est en arrière-plan, vous pouvez utiliser Xamarin.Forme.Application méthode OnSleep et OnResume comme décrit ici

6
répondu Ivan Bukashkin 2017-07-25 04:37:58

je fais quelque chose comme ceci est mes applications Xamarin Forms.

public void execute()
        {
            var thread = new Thread(new ThreadStart(startAuthenticationProcess))
            {
                IsBackground = true
            };
            thread.Start();
        }
 private void startAuthenticationProcess()
        {
            Thread.Sleep(2000);
            if (!Utils.isNetworkAvailable(splashActivity))
            {
                splashActivity.RunOnUiThread(() => Utils.showToast(splashActivity, splashActivity.GetString(Resource.String.r30025)));
                splashActivity.FinishAffinity();
            }
            else
            {
                try
                {
                    if (StringUtils.isBlank(strIPAdd) || (StringUtils.isNotBlank(strIPAdd) && (StringUtils.isBlank(strDbName) || "site".Equals(strDbName,StringComparison.OrdinalIgnoreCase))))
                    {
                        splashActivity.RunOnUiThread(() => DependencyService.Get<IAuthenticationDialog>().showAuthenticationDialog(new Command(() =>
                        {
                            var intent = new Intent(splashActivity, typeof(MainActivity));
                            intent.PutExtra("startLoginActivity", false);
                            splashActivity.StartActivity(intent);
                            splashActivity.Finish();
                        })));
                    }
                    else
                    {
                        gotoLoginScreen();
                    }
                }
                catch (Exception e)
                {
                    Log.Error(TAG, e.Message);
                }
            }
        }
4
répondu Abhinash 2017-07-26 10:23:05

Facile, essayez quelque chose comme ça et de mettre en œuvre votre logique de ces méthodes:

public partial class App : Application
{

   protected override void OnStart()
   {
      // Your App On start code should be here...

      // and then:
      Task.Run(() =>
        {
            //Add your code here, it might looks like:
            CheckDatabase();
            MakeAnUpdateDependingOnDatabase();
        });
   }

j'espère que cela aide.

3
répondu Juan 2017-07-27 11:38:10