如果前台应用程序正在执行,如何防止后台任务运行? 使用通用Windows平台为我的应用程序。
我的后台任务是检查某些站点上的新项目,并在有新事物时发送敬酒,但是如果用户现在正在运行应用程序,则无法防止敬酒发送。
我尝试在应用程序启动时取消注册任务,并在应用程序终止时再次注册,这对我来说不是很好的解决scheme – 当设备由于某种原因closures时(例如,电池被移除),我的任务将不会注册到应用程序再次启动。
谢谢。
使用一个已命名的互斥体在前台应用程序和后台代理之间进行同步
我会很乐意看到一个更简单的解决方案。 除此之外,你可以建立一个仲裁机制。 沿着这些线路的东西:
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中是否有任何方式进行沟通。 仲裁机制本身可能必须基于本地存储上的文件。
如果一个或另一个程序以灾难性的方式崩溃,仲裁机制可能必须包含一个心跳机制。
我有由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分钟后取消。
这与这个问题类似: 如果应用程序启动,如何停止后台任务?
最简单的方法是将您的任务转换为进程内后台任务: https : //docs.microsoft.com/en-us/windows/uwp/launch-resume/convert-out-of-process-background-task
使用进程内任务,您可以检查应用程序是否处于前台或直接从后台活动。
如果您需要将后台任务作为与主应用程序分开的进程,则可以执行以下任一操作: