2015-09-27 1 views
7

Как я могу предотвратить запуск фоновой задачи, если выполняется приложение переднего плана? Использование универсальной платформы Windows для моего приложения.Windows 10 UWP - остановка фоновой задачи при запуске приложения переднего плана

Моя фоновая задача проверяет наличие новых элементов на каком-либо сайте и отправляет тост, когда есть новые вещи, но я не хочу отправлять тосты, если пользователь запускает приложение прямо сейчас.

Я попытался отменить регистрацию задачи при запуске приложения и зарегистрировать его снова, когда приложение завершено, через это это не прекрасное решение для меня - когда устройство почему-то отключилось (например, батарея была удалена) задача не будет зарегистрирована, пока приложение не запустится снова.

Спасибо.

+1

Вы нашли решение? Вы используете задачу запуска приложения? – peterincumbria

ответ

0

Мне было бы очень интересно увидеть более простое решение. Не допуская этого, вы можете создать арбитражный механизм. Что-то вдоль этих линий:

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

В главном приложении:

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

И в фоновом режиме агента:

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

Я не уверен, есть ли способ общения между процессами в UWP. Сам механизм арбитража может основываться на файлах на локальном хранилище.

Арбитражный механизм, возможно, должен включать механизм сердечного ритма в случае, если один или другой процесс аварийно завершится катастрофическим образом.

+0

«Если основное приложение работает, это будет ждать бесконечно». (в задаче bg). Вы в этом уверены? Не запущены ли фоновые задачи, если они работают слишком долго? Или ожидание не учитывается как использование ЦП? Хотелось бы получить некоторые идеи, если это возможно. Спасибо :) – sibbl

+0

Если механизм арбитража, реализованный в ActivateBackgroundAgent, имеет цикл, в котором он спит через несколько секунд, то проверяет состояние основного приложения (возможно, путем изучения наличия файла, который создает основное приложение), тогда использование ЦП будет очень маленький. Время сна не учитывается. В конце концов, фоновый агент будет приостановлен, и вам придется подождать некоторое время, когда ОС возобновит его снова. Вы должны будете сделать много тестов вокруг этого, хотя. Насколько я знаю, фоновый агент в Windows 8.1 и WP 8.1 имел важные отличия. Не уверен насчет UWP. – Ladi

+0

В UWP, если DeviceUseTrigger не является триггером, фоновая задача будет отменена через 10 минут в случае запуска приложения. Это вызывает у меня настоящую боль при использовании приложения для отслеживания GPS, поскольку SensorCore теперь не рекомендуется. – peterincumbria

1

Используйте именованный мьютекс для синхронизации между передним планом приложением и фонового агентом

0

У меня есть backgroundtask, срабатывающий TimeTrigger. Эта задача перезапускается автоматически после перезагрузки телефона без необходимости загрузки приложения. Может быть, это помогло бы ...

[редактировать] только что понял, что я опоздал с моим ответом ...

0

Вы можете проверить состояние приложения, используя ниже код

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

способ сделать это - использовать локальные настройки приложения.

Установите настройку на переднем плане и на заднем плане. В качестве примера на переднем плане сделайте это.

/// <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; 
    } 
} 

К сожалению sibbi правильно, если вы не используете DeviceUseTrigger ваша фоновая задача будет отменить через 10 минут.

0

Это похоже на этот вопрос: How to stop the background task if the app is starting?

Самый простой способ будет конвертировать ваши задачи в-прок фоновых задач: https://docs.microsoft.com/en-us/windows/uwp/launch-resume/convert-out-of-process-background-task

С задачей-прок вы можете проверить, является ли приложение на переднем плане или не непосредственно из фоновой активности.

Если вам нужно сохранить свои задачи в фоновом режиме как отдельные процессы из основного приложения, то вы можете сделать одно из следующих действий:

  • Создать мьютекс с помощью файла.
  • Создайте службу приложений в proc и попытайтесь связаться с ней из своей фоновой задачи. Затем вы можете вернуть значение, находится ли приложение на переднем плане.
  • Используйте словарь локальных настроек приложения, чтобы иметь флаг о запуске приложения переднего плана. Это самый хрупкий, поскольку авария приложения может привести к неправильному сбросу флага.
Смежные вопросы