如果前台应用程序正在执行,如何防止后台任务运行?为我的应用程序使用通用Windows平台。Windows 10 UWP - 如果前台应用程序正在运行,则停止后台任务
我的后台任务是检查某个站点上的新项目,并在有新事物可用时发送敬酒,但是如果用户现在正在运行应用程序,我不想防止发送敬酒。
我试图在应用程序启动时取消注册任务,并在应用程序终止时再次注册,这对我来说不是很好的解决方案 - 当设备由于某种原因而关闭时(例如,电池被移除),我的任务将不会被注册,直到应用程序再次启动。
谢谢。
如果前台应用程序正在执行,如何防止后台任务运行?为我的应用程序使用通用Windows平台。Windows 10 UWP - 如果前台应用程序正在运行,则停止后台任务
我的后台任务是检查某个站点上的新项目,并在有新事物可用时发送敬酒,但是如果用户现在正在运行应用程序,我不想防止发送敬酒。
我试图在应用程序启动时取消注册任务,并在应用程序终止时再次注册,这对我来说不是很好的解决方案 - 当设备由于某种原因而关闭时(例如,电池被移除),我的任务将不会被注册,直到应用程序再次启动。
谢谢。
我会很乐意看到一个更简单的解决方案。除此之外,你可以建立仲裁机制。沿着这些路线的东西:
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。仲裁机制本身可能必须基于本地存储上的文件。
如果一个或另一个进程以灾难性方式崩溃,仲裁机制可能必须包含一个心跳机制。
“如果主应用程序正在运行,则将无限期等待。” (在bg任务中)。你确定吗?如果运行时间过长,后台任务是否会被终止?还是等待不算CPU使用率?如果可能的话,希望得到一些见解。谢谢:) – sibbl
如果在ActivateBackgroundAgent中实现的仲裁机制有一个休眠几秒钟的循环,然后检查主应用程序的状态(也许通过检查主应用程序创建的文件的存在),那么CPU使用率将是很小。睡眠时间不计算在内。最终,后台代理将被暂停,然后您需要等待一段时间才能让操作系统再次恢复。尽管如此,你将不得不做很多测试。据我所知,Windows 8.1和WP 8.1中的后台代理有重要的区别。不确定UWP。 – Ladi
在UWP中,如果DeviceUseTrigger不是触发器,则在应用程序触发器的情况下,后台任务将在10分钟后取消。由于SensorCore现在已被弃用,这使我对GPS跟踪应用程序感到非常痛苦。 – peterincumbria
使用一个名为互斥前台应用程序和后台代理
我有一个由TimeTrigger触发backgroundtask之间进行同步。该任务在手机重新启动后自动重启,无需首先加载应用程序。也许这将有助于...
[编辑]刚发现我迟到了我的回答...
您可以使用下面的代码检查应用程序的状态
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;
的这样做的方法是使用应用程序本地设置。
在前景和背景中设置设置。 作为前景中的一个示例,请执行此操作。
/// <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分钟后您的后台任务将取消。
这类似于这样的问题: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
随着进程内的任务,你可以检查应用程序是否是在前台或不直接从后台活动。
如果你需要保持你的后台任务分开处理的,从你的主应用程序,那么你可以做下列之一:
您是否找到解决方案?你在使用应用程序触发任务吗? – peterincumbria