我'm developing a UWP app which uses in-process background task to download new GitHub notifications and show them as toast notifications. I' m使用MVVM灯 . 我使用TimeTrigger尝试了进程内后台任务,当应用程序处于前台或最小化时,一切都按预期工作 . 但是当应用关闭时,后台任务就会停止工作 . 在监视任务管理器之后,我发现后台任务启动但在启动后立即关闭 . 所以我使用 ExtendedExecutionSession 来延长暂停时间 . 它仍然没有用 . 使用Out of the process后台任务可以解决上一个问题,但会引入一个新问题 . 由于进行API调用所需的应用程序数据(GitHub Auth Data)不可访问,GitHub api调用在后台失败 .
简而言之,我有以下问题:
-
在应用程序关闭时,进程后台任务不在后台运行
-
当我使用Octokit对GitHub进行API调用时,后台任务可以共享应用程序数据(例如我的GitHub Auth数据)
我发现了这些变通方法:
-
将 ExtendedExecutionSession 与进程内后台任务一起使用
-
在进程后台任务之外使用 Inter process communication
我的问题是:
-
如何以及何时在进程内任务中调用 ExtendedExecutionSession .
-
如何编码 Inter-process communication 以便能够从后台应用程序访问应用程序数据
请注意,我已在 MainPage.xaml.cs 中注册了后台任务 . 这是代码片段:
var syncBuilder = Helpers.BackgroundTaskHelper.BuildBackgroundTask(
"SyncNotifications",
new TimeTrigger(15, false),
internetAvailableCondition,
userPresentCondition,
sessionConnectedCondition
);
syncBuilder.IsNetworkRequested = true;
syncBuilder.Register();
我在 App.xaml.cs 中覆盖了 OnBackgroundActivated . 这是代码片段:
var deferral = args.TaskInstance.GetDeferral();
args.TaskInstance.Task.Completed += BackgroundTask_Completed;
var taskName = args.TaskInstance.Task.Name;
switch (taskName)
{
case "ToastNotificationBackgroundTask":
await CoreApplication
.MainView
.CoreWindow
.Dispatcher
.RunAsync(
CoreDispatcherPriority.Normal,
async () =>
{
var toastTriggerDetails = args.TaskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
var toastArgs = QueryString.Parse(toastTriggerDetails.Argument);
var notificationId = toastArgs["notificationId"];
if (!notificationId.IsNulloremptyOrNullorwhitespace())
{
await NotificationsService.MarkNotificationAsRead(notificationId);
}
});
break;
case "SyncNotifications":
await CoreApplication
.MainView
.CoreWindow
.Dispatcher
.RunAsync(
CoreDispatcherPriority.Normal,
async () =>
{
AppViewmodel.UnreadNotifications = await NotificationsService.GetAllNotificationsForCurrentUser(false, false);
await AppViewmodel.UnreadNotifications?.ShowToasts();
});
break;
}
1 回答
您的代码中的问题是您过早地完成了延迟,即在您的异步调度程序工作项有机会执行之前 . 当应用程序处于前台时,这种情况就会发生,因为无论如何都会保留该进程,但是当在后台激活时,该进程将一直运行,直到您将延迟标记为完成,这意味着它将在您的任务代码有机会之前退出跑 .
要了解我的意思,请尝试一下小实验 . 运行此代码,模拟调试器下的当前实现,并观察断点被命中的顺序 . 这将帮助您在实际代码运行之前意识到您正在调用Deferral.Complete:
现在,您的解决方案很简单,在您的任务实际完成后,将Deferral.Complete()调用移动到代码中的某个位置 . 您可能必须为此更改“延迟”的范围并创建类级变量 .