如果前臺應用程序正在執行,如何防止後臺任務運行?爲我的應用程序使用通用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