单进程 UWP 场景中的 TimeTrigger 未触发
TimeTrigger not firing in Single-Process UWP Scenario
最近几天我一直在用头撞显示器。我正在为 Windows 商店(目标 14393)开发一个 UWP 应用程序,我正在为 MVVM / IoC 使用 Prism/Unity 框架。
由于更新动态磁贴所需的数据存储在实现存储库模式的 class 中,并且所有内容都通过 Unity 进行管理,因此我没有为后台执行创建单独的进程,因此甚至简化了整个BGTask注册流程。
实际BGTask注册码如下:
var servicingTaskAlreadyRegistered = false;
var tileUpdaterTaskAlreadyRegistered = false;
foreach (var t in BackgroundTaskRegistration.AllTasks)
{
if (t.Value.Name == Constants.BgTileUpdaterTaskName)
tileUpdaterTaskAlreadyRegistered = true;
else if (t.Value.Name.Equals(Constants.BgServicingTaskName))
servicingTaskAlreadyRegistered = true;
}
var reqAccess = await BackgroundExecutionManager.RequestAccessAsync();
if (reqAccess == BackgroundAccessStatus.Denied ||
reqAccess == BackgroundAccessStatus.DeniedBySystemPolicy ||
reqAccess == BackgroundAccessStatus.DeniedByUser ||
reqAccess == BackgroundAccessStatus.Unspecified)
return false;
if (!servicingTaskAlreadyRegistered)
{
var servicingTaskBuilder = new BackgroundTaskBuilder();
servicingTaskBuilder.Name = Constants.BgServicingTaskName;
servicingTaskBuilder.SetTrigger(new SystemTrigger(SystemTriggerType.ServicingComplete, false));
servicingTaskBuilder.Register();
}
if (tileUpdaterTaskAlreadyRegistered)
return true;
var builder = new BackgroundTaskBuilder();
builder.Name = Constants.BgTileUpdaterTaskName;
builder.SetTrigger(new TimeTrigger(TileUpdateFrequencyMinutes, false));
//builder.SetTrigger(new MaintenanceTrigger(TileUpdateFrequencyMinutes, false));
builder.IsNetworkRequested = true;
builder.Register();
注册成功完成。在 PowerShell 中执行 Get-AppBackgroundTask 会显示这两个任务,这是应该的。但是,TimeTrigger 永远不会触发。用 MaintenanceTrigger 交换 TimeTrigger 解决了这个问题,尽管智能手机需要插入充电器,这是不可接受的解决方法。
通过 VisualStudio 或 PowerShell (Start-AppBackgroundTask -TaskID) 强制任务 运行 正确执行并且磁贴得到更新。
您还有其他有用的提示要分享吗?
编辑 12/01/2017
我创建了一个 Repro,其中包含一个 Visual Studio 解决方案和两个项目:
- 动态磁贴测试简单:使用 UWP 每 15 分钟更新一次动态磁贴非常简单。一切都按预期工作。
- Live Tile Test Prism:同样,使用 Prism 和 Unity 对上述项目进行简单转换。不起作用,因为当 OS 尝试启动应用程序以更新图块时,Unity 容器为空(未初始化)。
这解释了我遇到问题的原因:Unity 未初始化、我无法通过存储库检索数据、应用程序崩溃和 GG。
现在我只需要了解为什么 Unity 在 OnBackgroundActivated 方法中不可用。快到了!
代码对我来说看起来不错,我在这里尝试更改的唯一事情是 IsNetwokRequested
属性 和 TimeTrigger
频率值的使用,你确定吗您使用的 constant/variable 是否大于或等于 15?
这是一个示例:
BackgroundTaskBuilder builder = new BackgroundTaskBuilder { Name = "YourBgTaskName" };
builder.SetTrigger(new TimeTrigger(15, false));
builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
builder.Register();
好的,经过更多的测试,我终于想出了一个解决方案。
如前所述,问题源于 Prism:基本上,当由 OS 启动并通过 OnBackgroundActivated()
进入时,IoC 容器未被初始化。
解决方案,即使看起来 hack-ish,实际上是完全可行和正确的(恕我直言!)。在你的 OnBackgroundActivated()
中,就像从头开始一样初始化所有内容(查看 Prism's Source 了解实现细节):在我的具体情况下,我只是调用了 CreateAndConfigureContainer()
和 re-registered 一切我输入了 OnInitializeAsync()
(例如回购、服务..)。
我 opened an issue 与开发人员一起工作。也许解决方案已经在路上,但与此同时应该这样做。
最近几天我一直在用头撞显示器。我正在为 Windows 商店(目标 14393)开发一个 UWP 应用程序,我正在为 MVVM / IoC 使用 Prism/Unity 框架。
由于更新动态磁贴所需的数据存储在实现存储库模式的 class 中,并且所有内容都通过 Unity 进行管理,因此我没有为后台执行创建单独的进程,因此甚至简化了整个BGTask注册流程。
实际BGTask注册码如下:
var servicingTaskAlreadyRegistered = false;
var tileUpdaterTaskAlreadyRegistered = false;
foreach (var t in BackgroundTaskRegistration.AllTasks)
{
if (t.Value.Name == Constants.BgTileUpdaterTaskName)
tileUpdaterTaskAlreadyRegistered = true;
else if (t.Value.Name.Equals(Constants.BgServicingTaskName))
servicingTaskAlreadyRegistered = true;
}
var reqAccess = await BackgroundExecutionManager.RequestAccessAsync();
if (reqAccess == BackgroundAccessStatus.Denied ||
reqAccess == BackgroundAccessStatus.DeniedBySystemPolicy ||
reqAccess == BackgroundAccessStatus.DeniedByUser ||
reqAccess == BackgroundAccessStatus.Unspecified)
return false;
if (!servicingTaskAlreadyRegistered)
{
var servicingTaskBuilder = new BackgroundTaskBuilder();
servicingTaskBuilder.Name = Constants.BgServicingTaskName;
servicingTaskBuilder.SetTrigger(new SystemTrigger(SystemTriggerType.ServicingComplete, false));
servicingTaskBuilder.Register();
}
if (tileUpdaterTaskAlreadyRegistered)
return true;
var builder = new BackgroundTaskBuilder();
builder.Name = Constants.BgTileUpdaterTaskName;
builder.SetTrigger(new TimeTrigger(TileUpdateFrequencyMinutes, false));
//builder.SetTrigger(new MaintenanceTrigger(TileUpdateFrequencyMinutes, false));
builder.IsNetworkRequested = true;
builder.Register();
注册成功完成。在 PowerShell 中执行 Get-AppBackgroundTask 会显示这两个任务,这是应该的。但是,TimeTrigger 永远不会触发。用 MaintenanceTrigger 交换 TimeTrigger 解决了这个问题,尽管智能手机需要插入充电器,这是不可接受的解决方法。
通过 VisualStudio 或 PowerShell (Start-AppBackgroundTask -TaskID) 强制任务 运行 正确执行并且磁贴得到更新。
您还有其他有用的提示要分享吗?
编辑 12/01/2017 我创建了一个 Repro,其中包含一个 Visual Studio 解决方案和两个项目:
- 动态磁贴测试简单:使用 UWP 每 15 分钟更新一次动态磁贴非常简单。一切都按预期工作。
- Live Tile Test Prism:同样,使用 Prism 和 Unity 对上述项目进行简单转换。不起作用,因为当 OS 尝试启动应用程序以更新图块时,Unity 容器为空(未初始化)。
这解释了我遇到问题的原因:Unity 未初始化、我无法通过存储库检索数据、应用程序崩溃和 GG。
现在我只需要了解为什么 Unity 在 OnBackgroundActivated 方法中不可用。快到了!
代码对我来说看起来不错,我在这里尝试更改的唯一事情是 IsNetwokRequested
属性 和 TimeTrigger
频率值的使用,你确定吗您使用的 constant/variable 是否大于或等于 15?
这是一个示例:
BackgroundTaskBuilder builder = new BackgroundTaskBuilder { Name = "YourBgTaskName" };
builder.SetTrigger(new TimeTrigger(15, false));
builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
builder.Register();
好的,经过更多的测试,我终于想出了一个解决方案。
如前所述,问题源于 Prism:基本上,当由 OS 启动并通过 OnBackgroundActivated()
进入时,IoC 容器未被初始化。
解决方案,即使看起来 hack-ish,实际上是完全可行和正确的(恕我直言!)。在你的 OnBackgroundActivated()
中,就像从头开始一样初始化所有内容(查看 Prism's Source 了解实现细节):在我的具体情况下,我只是调用了 CreateAndConfigureContainer()
和 re-registered 一切我输入了 OnInitializeAsync()
(例如回购、服务..)。
我 opened an issue 与开发人员一起工作。也许解决方案已经在路上,但与此同时应该这样做。