Windows 10 UWP - 如果前台应用程序正在运行,则停止后台任务

时间:2015-09-27 07:44:59

标签: c# windows windows-phone uwp background-task

如果正在执行前台应用程序,如何阻止后台任务运行?为我的应用程序使用通用Windows平台。

我的后台任务是检查某些网站上的新项目,并在有新内容可用时发送一个祝酒词,但如果用户现在正在运行应用程序,我就不会阻止发送请求。

我试图在我的应用程序启动时取消注册任务并在应用程序终止时再次注册,通过,这对我来说不是很好的解决方案 - 当设备由于某种原因关闭时(例如,电池被移除)我的任务在app再次发布之前不会注册。

感谢。

6 个答案:

答案 0 :(得分:2)

使用指定的互斥锁在前台应用程序和后台代理程序之间进行同步

答案 1 :(得分: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中跨进程进行通信。仲裁机制本身可能必须基于本地存储上的文件。

如果一个或另一个进程以灾难性方式崩溃,仲裁机制可能必须包括心跳机制。

答案 2 :(得分:0)

我有一个由TimeTrigger触发的backgroundtask。电话重启后,该任务会自动重启,无需先加载应用程序。也许这会有所帮助......

[编辑]刚刚意识到我的回答迟到了......

答案 3 :(得分: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;

答案 4 :(得分: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分钟后取消。

答案 5 :(得分: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

使用进程内任务,您可以直接从后台活动检查应用程序是否在前台。

如果您需要将后台任务作为与主应用程序不同的进程,那么您可以执行以下操作之一:

  • 通过文件创建互斥锁。
  • 创建一个进程内应用程序服务,并尝试从后台任务与之通信。然后,您可以返回值,无论应用程序是否在前台。
  • 使用应用程序本地设置字典保存有关前台应用程序是否正在运行的标志。这是最脆弱的,因为应用程序崩溃可能导致标记无法正确重置。