未加星标

Windows 10 1607, UWP and Extended Execution

字体大小 | |
[系统(windows) 所属分类 系统(windows) | 发布者 店小二03 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

I had a feeling that I’ve written about ExtendedExecutionSession before and I know that I spoke about it in a session that I did on background work in WinRT apps that I delivered back at TechDays in the Netherlands in 2015.

It took a little search through my blog to find that I had indeed written up something about it in a previous post;

windows 10 Universal Windows Apps and Background Work

and that included some topics like;

the app lifecycle and why it means you need background work extended execution notifications background transfers background tasks

but the arrival of the Anniversary Update build 1607 makes some of that somewhat out of date in that there have been changes to many of these areas and I made reference to some of the links on these areas in this recent post;

Windows 10 1607, UWP, Single Process Execution and Lifecycle Changes

and so I won’t repeat those links here.

Today, though, I took some of the code that I’d shown in that TechDays session around “Extended Execution” and I brought it forward to the current 14393 UWP SDK and I found that it didn’t work and that surprised me and so I thought I would note that here.

As a quick re-cap: UWP apps are suspended (and possibly terminated) when the user is not actively using them and extended execution is a way to ask the system to take your app out of that suspend/resume process and you can use it in two ways;

As a blanket ‘up front’ request that the system doesn’t suspend you. Naturally, the system can say ‘no’ and it can also change its mind at a later point. As a request from your ‘suspending’ event handler to let the system know that you need more time.

To experiment with this I made a simple, blank app with this super-simple UserControl as the UI;

<UserControl x:Class="App52.MyUIControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App52" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Viewbox> <Grid Margin="4"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBlock TextAlignment="Center" x:Name="txtTime" /> <Button Grid.Row="1" HorizontalAlignment="Stretch" x:Name="btnExtended" Content="Go Extended" /> <Button Grid.Row="2" HorizontalAlignment="Stretch" x:Name="btnLeaveExtended" Content="Leave Extended" /> </Grid> </Viewbox> </UserControl>

and some code behind which changes the value of the TextBlock and which allows a caller to subscribe/unsubscribe event handlers to the 2 buttons;

namespace App52 { using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; public sealed partial class MyUIControl : UserControl { public MyUIControl() { this.InitializeComponent(); } public void SetText(string text) { this.txtTime.Text = text; } public void SetClearExtendedHandler(RoutedEventHandler handler, bool clear=false) { SetClearClickHandler(this.btnExtended, handler, clear); } public void SetClearUnextendedHandler(RoutedEventHandler handler, bool clear=false) { SetClearClickHandler(this.btnLeaveExtended, handler, clear); } static void SetClearClickHandler(Button button, RoutedEventHandler handler, bool clear) { if (!clear) { button.Click += handler; } else { button.Click -= handler; } } } }

and then I removed the MainPage.xaml/MainPage.xaml.cs files from my project and replaced the App.xaml.cs code with the below;

namespace App52 { using System; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.ExtendedExecution; using Windows.UI.Xaml; sealed partial class App : Application { public App() { this.InitializeComponent(); this.EnteredBackground += OnEnteredBackground; this.LeavingBackground += OnLeavingBackground; this.Suspending += OnSuspending; this.startTime = DateTime.Now; this.timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) }; this.timer.Tick += OnTimerTick; this.timer.Start(); } protected override void OnLaunched(LaunchActivatedEventArgs args) { Window.Current.Activate(); } void OnLeavingBackground(object sender, LeavingBackgroundEventArgs e) { this.isBackground = false; this.CreateUI(); } void OnEnteredBackground(object sender, EnteredBackgroundEventArgs e) { this.DestroyUI(); this.isBackground = true; } void OnTimerTick(object sender, object e) { if (this.isBackground) { this.backgroundTimeSeconds++; } else { this.regularTimeSeconds++; this.UpdateUI(); } } void UpdateUI() { var elapsed = (DateTime.Now - this.startTime).TotalSeconds; var total = this.regularTimeSeconds + this.backgroundTimeSeconds; // lazy, should use stringbuilder. this.uiControl.SetText( $"regular {this.regularTimeSeconds}\n" + $"background {this.backgroundTimeSeconds}\n" + $"total (r + b) {this.regularTimeSeconds + this.backgroundTimeSeconds}\n" + $"elapsed {elapsed:N0}\n" + $"missing {elapsed - total:N0}"); } void CreateUI() { this.uiControl = new MyUIControl(); this.uiControl.SetClearExtendedHandler(this.OnExtendedMode); this.uiControl.SetClearUnextendedHandler(this.OnUnextendedMode); Window.Current.Content = this.uiControl; } void DestroyUI() { this.uiControl.SetClearExtendedHandler(this.OnExtendedMode, true); this.uiControl.SetClearUnextendedHandler(this.OnUnextendedMode, true); this.uiControl = null; Window.Current.Content = null; } async void OnExtendedMode(object sender, RoutedEventArgs e) { if (this.extendedExecutionSession == null) { this.extendedExecutionSession = new ExtendedExecutionSession() { Reason = ExtendedExecutionReason.LocationTracking, Description = "locating tracking" }; this.extendedExecutionSession.Revoked += OnExtensionRevoked; var result = await this.extendedExecutionSession.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Allowed) { // We're running extended. } else { // We're not. this.OnUnextendedMode(null, null); } } } void OnExtensionRevoked(object sender, ExtendedExecutionRevokedEventArgs args) { this.OnUnextendedMode(null, null); } void OnUnextendedMode(object sender, RoutedEventArgs e) { if (this.extendedExecutionSession != null) { this.extendedExecutionSession.Dispose(); this.extendedExecutionSession = null; } } void OnSuspending(object sender, SuspendingEventArgs e) { // deliberately nothing here. } ExtendedExecutionSession extendedExecutionSession; int regularTimeSeconds; int backgroundTimeSeconds; bool isBackground; MyUIControl uiControl; DispatcherTimer timer; DateTime startTime; } }

What’s this intended to do? It’s trying to keep a track of the number of seconds that a 1-second timer in the app is actively firing versus the total elapsed time that the app has been running. It’s also trying to partition those 1-second timer ticks into ‘foreground’ and ‘background’ categories.

It’s not intended to survive suspend/terminate/launch.

If I run this app outside of the debugger for ~10 seconds then I’m going to see output like;


Windows 10 1607, UWP and Extended Execution

Now, if I minimise the app at the 10 second mark and then maximise it around 20 seconds later I see something like;


Windows 10 1607, UWP and Extended Execution

Ok no surprise. My app has been ‘alive’ for around 34 seconds. Of that, for 13 seconds my app was getting timer ticks in the foreground. For 6 seconds it was getting them in the background and then for 15 seconds it didn’t get any timer ticks because the app was suspended.

Now, what surprised me is that I then repeated my experiment after clicking the ‘Go Extended’ button to request ‘extended execution’ with the event handler running the same code that I’d been running back at TechDays a little more than a year ago. That is this code;

async void OnExtendedMode(object sender, RoutedEventArgs e) { if (this.extendedExecutionSession == null) { this.extendedExecutionSession = new ExtendedExecutionSession() { Reason = ExtendedExecutionReason.LocationTracking, Description = "locating tracking" }; this.extendedExecutionSession.Revoked += OnExtensionRevoked; var result = await this.extendedExecutionSession.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Allowed) { // We're running extended. } else { // We're not. this.OnUnextendedMode(null, null); } } }

Here’s what I saw after around 30 seconds repeating that experiment;


Windows 10 1607, UWP and Extended Execution

Hmmm I’m still missing 15 seconds of timer ticks here. I seem to have not managed to go into extended mode and if I debug this I see;


Windows 10 1607, UWP and Extended Execution

which explains it. The question was then what to do about that and I wondered whether the previous ‘get out of jail’ of providing a reason of “location” was no longer valid for an app that’s not actually doing that. I changed that code;

this.extendedExecutionSession = new ExtendedExecutionSession() { Reason = ExtendedExecutionReason.Unspecified, // Change! Description = "general playing around" };

and, sure enough, repeating my experiment for around 30 seconds again gave me more like the result I was expecting;


Windows 10 1607, UWP and Extended Execution
i.e. pretty much no time lost to suspension when I’ve asked for extended execution so just recording that here in case someone else comes across it (including me in the future
Windows 10 1607, UWP and Extended Execution
).

本文系统(windows)相关术语:三级网络技术 计算机三级网络技术 网络技术基础 计算机网络技术

主题: WindowsUWUIC
分页:12
转载请注明
本文标题:Windows 10 1607, UWP and Extended Execution
本站链接:http://www.codesec.net/view/483732.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(windows) | 评论(0) | 阅读(39)