UWP 后台任务在 5 次后没有 运行
UWP Background Task not running after 5 times
我正在按照 https://docs.microsoft.com/en-us/windows/uwp/launch-resume/create-and-register-a-background-task 文档创建一个后台任务,该任务将 运行 每 15 分钟并 ping 一个服务。
创建了一个 Windows 运行时组件项目,其中 public 密封 class 实现 IBackgroundTask
namespace PeriodicBackgroundTask
{
public sealed class FifteenMinutePeriodicTimer : IBackgroundTask
{
private static readonly FileLogWriter mWriteLogToFile = new FileLogWriter();
public FifteenMinutePeriodicTimer() { }
public void Run(IBackgroundTaskInstance taskInstance)
{
try
{
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
mDeferral = taskInstance.GetDeferral();
mWriteLogToFile.log("Starting periodic timer at " + DateTime.Now.ToString());
// Calling method to do a Post call to a service.
mWriteLogToFile.log("Finishing periodic timer at " + DateTime.Now.ToString());
}
catch (Exception ex)
{
mWriteLogToFile.log("Fifteen Minute periodic timer failed.", ex);
}
finally
{
// Adding some buffer for async processes to finish.
Task.Delay(TimeSpan.FromSeconds(15)).Wait();
mDeferral.Complete();
}
}
private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
mWriteLogToFile.log("Fifteen minute periodic timer is canceled. {0}", reason.ToString());
}
}
}
UWP 应用程序的 Package.appmanifest 文件中的条目
<Extension Category="windows.backgroundTasks" EntryPoint="PeriodicBackgroundTask.FifteenMinutePeriodicTimer">
<BackgroundTasks>
<Task Type="systemEvent" />
<Task Type="timer" />
</BackgroundTasks>
</Extension>
在App.xaml.cs
的OnLaunched方法开头注册定时器
public async static Task RegisterBackgroundTask()
{
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if (String.Equals(task.Value.Name, TASK_NAME))
{
mWriteLogToFile.log("Old version of fifteen minute periodic timer found. Unregistering it.");
BackgroundExecutionManager.RemoveAccess();
// Unregistering so that any update in Background task can be applied.
task.Value.Unregister(true);
break;
}
}
BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
if (backgroundAccessStatus == BackgroundAccessStatus.DeniedByUser ||
backgroundAccessStatus == BackgroundAccessStatus.DeniedBySystemPolicy)
{
mWriteLogToFile.log("Fifteen minute periodic timer registration failed, due to Request access status.");
return;
}
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = TASK_NAME;
builder.TaskEntryPoint = "PeriodicBackgroundTask.FifteenMinutePeriodicTimer";
builder.SetTrigger(new TimeTrigger(15, false));
builder.CancelOnConditionLoss = false;
var backgroundTask = builder.Register();
if (backgroundTask != null)
{
mWriteLogToFile.log("Fifteen minute periodic timer registration SUCCESSFUL.");
}
else
{
mWriteLogToFile.log("Fifteen minute periodic timer registration FAILED.");
}
}
安装应用程序 FifteenMinuteBackgroundTimer 运行s 5 或 6 次后。有时 5,有时 6。当我尝试使用 Visual Studio 调试任务时,我能够调试它。我不确定,为什么 FifteenMinuteBackgroundTimer 在 5 运行s 后就死了。谁能告诉我如何调试这个问题?
更多信息:
Windows 建造:1607
Microsoft.NETCore.UniversalWindowsPlatform: 5.1.0
Can anybody please tell me how can I debug this issue?
注册后台任务后,您会发现后台任务显示在生命周期事件工具栏的下拉列表中。在后台任务上设置一个断点,然后点击工具栏中的后台名称visual studio将触发后台任务,您可以调试。更多详情请参考Debug a background task.
why FifteenMinuteBackgroundTimer is dying after 5 runs.
如果你 运行 后台任务中有任何异步代码,那么你的后台任务需要使用 deferral.It 看起来你创建了延迟实例但没有从 IBackgroundTaskInstance
。所以你可能需要先申请延期。
public void Run(IBackgroundTaskInstance taskInstance)
{
mDeferral = taskInstance.GetDeferral();
...
mDeferral.Complete();
}
而且您可能不需要 Task.Delay(TimeSpan.FromSeconds(15)).Wait();
为异步进程添加一些缓冲区来完成,因为延迟可以帮助您做到这一点。后台任务一共只能运行30s,实际运行ning时间可能只有25s,后台任务如果设置延迟可能会导致无法完成任务而强制关闭。
您很可能 运行 陷入两项与权力相关的政策。
- 定期计时器触发器被认为是机会主义的。根据后台使用的能量(未通电和屏幕关闭时),您的任务可能不会被触发,以便为其他关键用户活动(如接收短信、推送或传入 phone 节省能量称呼)。
要验证这是否是您 运行 的情况:您可以在 "settings->system->battery->battery by application" 面板中将您的应用程序切换到 "always allowed"。
- 您还提到,当您的触发器在屏幕关闭时运行时,网络无法正常工作。在备用系统中,您需要将 IsNetworkRequested 指定为触发器注册的一部分,以便系统在您的任务期间将网络接口置于完全运行模式。
请参阅此处的文档:https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder
我正在按照 https://docs.microsoft.com/en-us/windows/uwp/launch-resume/create-and-register-a-background-task 文档创建一个后台任务,该任务将 运行 每 15 分钟并 ping 一个服务。
创建了一个 Windows 运行时组件项目,其中 public 密封 class 实现 IBackgroundTask
namespace PeriodicBackgroundTask { public sealed class FifteenMinutePeriodicTimer : IBackgroundTask { private static readonly FileLogWriter mWriteLogToFile = new FileLogWriter(); public FifteenMinutePeriodicTimer() { } public void Run(IBackgroundTaskInstance taskInstance) { try { taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled); mDeferral = taskInstance.GetDeferral(); mWriteLogToFile.log("Starting periodic timer at " + DateTime.Now.ToString()); // Calling method to do a Post call to a service. mWriteLogToFile.log("Finishing periodic timer at " + DateTime.Now.ToString()); } catch (Exception ex) { mWriteLogToFile.log("Fifteen Minute periodic timer failed.", ex); } finally { // Adding some buffer for async processes to finish. Task.Delay(TimeSpan.FromSeconds(15)).Wait(); mDeferral.Complete(); } } private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { mWriteLogToFile.log("Fifteen minute periodic timer is canceled. {0}", reason.ToString()); } } }
UWP 应用程序的 Package.appmanifest 文件中的条目
<Extension Category="windows.backgroundTasks" EntryPoint="PeriodicBackgroundTask.FifteenMinutePeriodicTimer"> <BackgroundTasks> <Task Type="systemEvent" /> <Task Type="timer" /> </BackgroundTasks> </Extension>
在App.xaml.cs
的OnLaunched方法开头注册定时器public async static Task RegisterBackgroundTask() { foreach (var task in BackgroundTaskRegistration.AllTasks) { if (String.Equals(task.Value.Name, TASK_NAME)) { mWriteLogToFile.log("Old version of fifteen minute periodic timer found. Unregistering it."); BackgroundExecutionManager.RemoveAccess(); // Unregistering so that any update in Background task can be applied. task.Value.Unregister(true); break; } } BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync(); if (backgroundAccessStatus == BackgroundAccessStatus.DeniedByUser || backgroundAccessStatus == BackgroundAccessStatus.DeniedBySystemPolicy) { mWriteLogToFile.log("Fifteen minute periodic timer registration failed, due to Request access status."); return; } BackgroundTaskBuilder builder = new BackgroundTaskBuilder(); builder.Name = TASK_NAME; builder.TaskEntryPoint = "PeriodicBackgroundTask.FifteenMinutePeriodicTimer"; builder.SetTrigger(new TimeTrigger(15, false)); builder.CancelOnConditionLoss = false; var backgroundTask = builder.Register(); if (backgroundTask != null) { mWriteLogToFile.log("Fifteen minute periodic timer registration SUCCESSFUL."); } else { mWriteLogToFile.log("Fifteen minute periodic timer registration FAILED."); } }
安装应用程序 FifteenMinuteBackgroundTimer 运行s 5 或 6 次后。有时 5,有时 6。当我尝试使用 Visual Studio 调试任务时,我能够调试它。我不确定,为什么 FifteenMinuteBackgroundTimer 在 5 运行s 后就死了。谁能告诉我如何调试这个问题?
更多信息:
Windows 建造:1607
Microsoft.NETCore.UniversalWindowsPlatform: 5.1.0
Can anybody please tell me how can I debug this issue?
注册后台任务后,您会发现后台任务显示在生命周期事件工具栏的下拉列表中。在后台任务上设置一个断点,然后点击工具栏中的后台名称visual studio将触发后台任务,您可以调试。更多详情请参考Debug a background task.
why FifteenMinuteBackgroundTimer is dying after 5 runs.
如果你 运行 后台任务中有任何异步代码,那么你的后台任务需要使用 deferral.It 看起来你创建了延迟实例但没有从 IBackgroundTaskInstance
。所以你可能需要先申请延期。
public void Run(IBackgroundTaskInstance taskInstance)
{
mDeferral = taskInstance.GetDeferral();
...
mDeferral.Complete();
}
而且您可能不需要 Task.Delay(TimeSpan.FromSeconds(15)).Wait();
为异步进程添加一些缓冲区来完成,因为延迟可以帮助您做到这一点。后台任务一共只能运行30s,实际运行ning时间可能只有25s,后台任务如果设置延迟可能会导致无法完成任务而强制关闭。
您很可能 运行 陷入两项与权力相关的政策。
- 定期计时器触发器被认为是机会主义的。根据后台使用的能量(未通电和屏幕关闭时),您的任务可能不会被触发,以便为其他关键用户活动(如接收短信、推送或传入 phone 节省能量称呼)。 要验证这是否是您 运行 的情况:您可以在 "settings->system->battery->battery by application" 面板中将您的应用程序切换到 "always allowed"。
- 您还提到,当您的触发器在屏幕关闭时运行时,网络无法正常工作。在备用系统中,您需要将 IsNetworkRequested 指定为触发器注册的一部分,以便系统在您的任务期间将网络接口置于完全运行模式。 请参阅此处的文档:https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder