2015-09-27 10 views
7

Wie kann ich verhindern, dass Hintergrund-Task ausgeführt wird, wenn eine Vordergrund-App ausgeführt wird? Universal Windows Platform für meine App verwendenWindows 10 UWP - Hintergrund-Task stoppen, wenn Vordergrund-App läuft

Meine Hintergrundaufgabe sucht nach neuen Elementen auf einer Website und sendet einen Toast, wenn neue Dinge verfügbar sind, aber ich möchte verhindern, dass Toast gesendet wird, wenn der Benutzer gerade eine Anwendung ausführt.

Ich habe versucht, Aufgabe auf meinem Anwendungsstart aufzuheben und es erneut zu registrieren, wenn App beendet wird, durch, das ist keine gute Lösung für mich - wenn das Gerät aus irgendeinem Grund heruntergefahren wird (z. B. Batterie wurde entfernt) Die Aufgabe wird erst registriert, wenn die App erneut gestartet wird.

Danke.

+1

Haben Sie eine Lösung gefunden? Verwenden Sie eine Anwendungsauslöser-Task? – peterincumbria

Antwort

0

Ich wäre sehr daran interessiert, eine einfachere Lösung zu sehen. Abgesehen davon können Sie einen Schlichtungsmechanismus einrichten. Etwas in diese Richtung:

public class AppSynchronization 
{ 
    // Called by the main app on launch or on resume. It will signal the main app's intention to start. 
    // The main app will not perform any significant actions before this method returns. 
    public void ActivateMainApp() {...} 

    // Called by the main app. It will signal the fact that the main app is "going away". 
    public async Task MainAppSuspended() {...} 

    // Called by the background agent. 
    // It will signal the background agent intention to start. 
    // This method will only return if the main app is out of the way. 
    // It will return a cancellation token that will be used to cancel the activity of the background agent when the main app advertises its intention to start. 
    public async Task<CancellationToken> ActivateBackgroundAgent(CancellationToken cancelWait) 
    { 
     // Make sure the main app is not started or wait until the main app is out of the way 

     // Start a thread that is on the lookout for the main app announcing that it wants to start. 
     // When that happens it will cancel the cancellation token returned. 
    } 

    // <summary> 
    // Called by the background agent. 
    // It will signal the fact that the background agent completed its actions. 
    public async Task DeactivateBackgroundAgent() 
} 

Im Haupt App:

private AppSynchronization appSynchronization; 

public App() 
{ 
    ... 
    this.appSynchronization = new AppSynchronization(); 
} 

protected async override void OnLaunched(LaunchActivatedEventArgs e) 
{ 
    ... 
    if (rootFrame.Content == null) 
    { 
     // Advertise the fact that the main app wants to start. 
     // The background agent will know to cancel whatever its doing. 
     // ActivateMainApp may have to be async although you need to make sure that OnLaunched supports that 
     this.appSynchronization.ActivateMainApp(); 
     ... 
    } 
} 

private async void OnResuming(object sender, object e) 
{ 
    ... 
    // Advertise the fact that the main app wants to resume. 
    // The background agent will know to cancel whatever its doing. 
    this.appSynchronization.ActivateMainApp(); 
} 


private async void OnSuspending(object sender, SuspendingEventArgs e) 
{ 
    var deferral = e.SuspendingOperation.GetDeferral(); 

    ... 
    // Advertise the fact that the main app is suspending. 
    // The background agent will know it is allowed to start doing work. 
    await _mainAppSynchronization.MainAppSuspended(); 

    ... 
    deferral.Complete(); 
} 

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) 
{ 
    ... 
    // Advertise the fact that the main app is going away. 
    // The background agent will know it is allowed to start doing work. 
    _mainAppSynchronization.MainAppSuspended().Wait(); 
} 

Und im Hintergrund Mittel:

public sealed class BackgroundTask : IBackgroundTask 
{ 
    public async void Run(IBackgroundTaskInstance taskInstance) 
    { 
     ... 
     AppSynchronization appSynchronization = new AppSynchronization(); 
     BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); 

     // Make sure that the main app is not started. If it is started then wait until the main app gets out of the way. 
     // It he main app is running this will wait indefinitely. 
     // Use backgroundAgentCancellationToken to cancel the actions of the background agent when the main app advertises its intention to start. 
     CancellationToken backgroundAgentCancellationToken = await appSynchronization.ActivateBackgroundAgent(); 

     await DoBackgroundAgentWork(backgroundAgentCancellationToken) 

     // Advertise the fact that the background agent is out. 
     // DeactivateBackgroundAgent will make sure that the synchronization mechanism advertised the fact that the background agent is out. 
     // DeactivateBackgroundAgent may have to be declared async in case the synchronization mechanism uses async code to do what is needed. 
     await appSynchronization.DeactivateBackgroundAgent(); 

     deferral.Complete(); 
    } 

Ich bin nicht sicher, ob es eine Möglichkeit, über Prozesse zu kommunizieren in UWP. Der Arbitrierungsmechanismus selbst muss möglicherweise auf Dateien auf dem lokalen Speicher basieren.

Der Arbitrierungsmechanismus muss möglicherweise einen Heartbeat-Mechanismus enthalten, falls der eine oder andere Prozess auf eine katastrophale Weise abstürzt.

+0

"Wenn die Haupt-App läuft, wird dies auf unbestimmte Zeit warten." (in der BG-Aufgabe). Bist du dir sicher? Werden Hintergrundaufgaben nicht abgebrochen, wenn sie zu lange laufen? Oder zählt das Warten nicht als CPU-Auslastung? Würde gerne ein paar Einblicke bekommen, wenn möglich. Danke :) – sibbl

+0

Wenn der in ActivateBackgroundAgent implementierte Arbitrierungsmechanismus eine Schleife hat, in der er ein paar Sekunden lang schläft, dann prüft er den Status der Hauptanwendung (vielleicht durch Untersuchung des Vorhandenseins einer Datei, die die Hauptanwendung erstellt) und dann die CPU-Auslastung sehr klein. Die Schlafzeit wird nicht gezählt. Schließlich wird der Hintergrund-Agent angehalten und Sie müssen einige Zeit warten, bis das Betriebssystem den Vorgang wieder aufnimmt. Sie müssen jedoch eine Menge Tests um dies tun. Soweit ich weiß, hatte der Hintergrundagent in Windows 8.1 gegenüber WP 8.1 wichtige Unterschiede. Nicht sicher über UWP. – Ladi

+0

In UWP, wenn DeviceUseTrigger nicht der Auslöser ist, wird die Hintergrundaufgabe im Falle eines Anwendungstriggers nach 10 Minuten abgebrochen. Dies verursacht mir echte Schmerzen mit einer GPS-Tracking-App, da SensorCore jetzt veraltet ist. – peterincumbria

1

einen benannten Mutex verwenden zwischen App im Vordergrund und dem Hintergrund Agent

0

Ich habe Background zu synchronisieren, die durch TimeTrigger ausgelöst wird. Diese Aufgabe wird nach dem Neustart des Telefons automatisch neu gestartet, ohne dass zuvor eine App geladen werden muss. Vielleicht würde das helfen ...

[bearbeitet] nur realisiert, ich bin spät mit meiner Antwort zu sein ...

0

Sie können den Status der App überprüfen unten Code

var value = ApplicationSettingsHelper.ReadResetSettingsValue(ApplicationSettingsConstants.AppState); 
if (value == null) 
    foregroundAppState = AppState.Unknown; 
else 
    foregroundAppState = EnumHelper.Parse<AppState>(value.ToString()); 

if (foregroundAppState == AppState.Suspended) 
     //Do something 
else if (foregroundAppState == AppState.Active) 
     return; 
else if (foregroundAppState == AppState.Unknown) 
     return; 
0

Die So können Sie lokale Anwendungseinstellungen verwenden.

Legen Sie die Einstellung im Vordergrund und im Hintergrund fest. Als Beispiel im Vordergrund dies tun.

/// <summary> 
/// When the window visibility changes 
/// </summary> 
/// <param name="sender">object sender</param> 
/// <param name="e">VisibilityChangedEventArgs e</param> 
private void OnVisibilityChanged(object sender, VisibilityChangedEventArgs e) 
{ 
    var localSettings = ApplicationData.Current.LocalSettings; 

    if (!e.Visible) 
    { 
     localSettings.Values["AppInForeground"] = false;    
    } 
    else 
    { 
     localSettings.Values["AppInForeground"] = true; 
    } 
} 

Leider ist Sibbi richtig, wenn Sie nicht die DeviceUseTrigger Aufgabe Ihren Hintergrund verwenden wird nach 10 Minuten gelöscht werden.

0

Das auf diese Frage ähnlich ist: How to stop the background task if the app is starting?

Der einfachste Weg, Ihre Aufgaben in-proc Hintergrundaufgaben würde konvertieren: Aufgabe https://docs.microsoft.com/en-us/windows/uwp/launch-resume/convert-out-of-process-background-task

Mit einem In-proc können Sie die App überprüfen, ob ist im Vordergrund oder nicht direkt von der Hintergrundaktivität.

Wenn Sie Ihre Hintergrundaufgaben als separate Prozesse von Ihrem Haupt-App halten müssen, dann können Sie eine der folgenden Aktionen ausführen:

  • erstellen Mutex über eine Datei.
  • Erstellen Sie einen in-proc-App-Dienst, und versuchen Sie, über Ihre Hintergrundaufgabe mit ihm zu kommunizieren. Dann können Sie einen Wert zurückgeben, ob die App im Vordergrund ist.
  • Verwenden Sie das App Local Settings Dictionary, um ein Flag darüber zu halten, ob die App im Vordergrund ausgeführt wird. Dies ist am anfälligsten, da ein Absturz der App dazu führen kann, dass die Flagge nicht korrekt zurückgesetzt wird.