środa, 2 maja 2012

Notatki o Windows 8 Consumer Preview - odc. 23

Tym razem trochę zmian, które wyłapałem dla tasków w tle w wersji Consumer Preview. Diametralnych zmian nie ma, aczkolwiek pojawiły się pewne modyfikacje oraz całkiem nowe zagadnienia. Moją uwagę zwróciły:

  • nowe rodzaje triggerów
  • fakt, że nie wszystkie triggery wymagają, by aplikacja była na lock-screen
  • fakt przekazywania do uśpionych aplikacji po ich wybudzeniu informacji o zakończeniu/progresie w tasku
  • fakt, że nie wszystkie rodzaje triggerów pozwalają na wybór hosta między oddzielnym procesem “systemowym” a procesem aplikacji
  • obsługa asynchroniczności w kodzie taska w C# i C++ w taki sposób, by tak nie zakończył się wcześniej zanim pokończą się asynchroniczne wywołania
  • zmieniony obiekt taska dla Java Script
  • zróżnicowane restrykcje procesora w zależności od tego, czy aplikacja jest w lock-screen (te poza nim mają gorzej)
  • restrykacje dla komunikacji sieciowej w przypadku pracy na baterii (limity przepustowości)
  • taski krytyczne ograniczone jedynie quotą aplikacji na zasoby
  • współdzielona pomiędzy aplikacjami globalna pula z zasobami procesora i sieciowymi na wypadek przekroczenia limitu zagwarantowanych dla aplikacji zasobów

Background Tasks

  • ControlChannelTrigger - On incoming messages on the control channel.
  • InternetAvailable
  • InternetNotAvailable
  • LockScreenApplicationAdded
  • LockScreenApplicationRemoved
  • MaintenanceTrigger - It’s time for maintenance background tasks.
  • NetworkNotificationChannelReset
  • NetworkStateChange
  • OnlineIdConnectedStateChange - Online ID associated with the account changes.
  • PushNotificationTrigger - A raw notification arrives on the WNS channel.
  • ServicingComplete
  • SessionConnected
  • SessionDisconnected
  • SessionStart
  • SmsReceived
  • TimeTrigger
  • TimeZoneChange
  • UserAway
  • UserPresent

Every app that is on the lock screen must implement a background task of either the Control Channel, Timer, or Push Notification type.

Access to specific types of triggers is restricted to only apps on the lock screen.

  • TimeTrigger, PushNotificationTrigger, ControlChannelTrigger - lock-screen required
  • SystemTrigger* (except of SessionStart), MaintenanceTrigger - lock-screen not required

Apps that are not on the lock screen cannot use certain types of triggers, and they also have much lower resource quotas available to them.

An app can programmatically add itself to the lock screen by using the BackgroundExecutionManager class.

All background task registrations are persistent (except for Control Channel background tasks); that is, the app doesn’t have to be running for the background task to be triggered.

The app must register a progress handler to receive progress updates from the background task when the app is in the foreground. The progress handler in the app does not receive the updates from the background task if the app is terminated. If the app was suspended when the task sent the progress, it will receive it next time the app is resumed.

If the app was suspended when the task completed, it will receive the completion notification next time the app is resumed. If the app was in the Terminated state, it does not receive the completion notification.

When an app is uninstalled, all its background task registrations are deleted from the system.

Only background tasks that contain PushNotificationTrigger or ControlChannelTrigger task types can specify an executable other than BackgroundTaskHost.exe.

  • TimeTrigger, SystemTrigger, MaintenanceTrigger - BackgroundTaskHost.exe
  • PushNotificationTrigger - Application or BackgroundTaskHost.exe
  • ControlChannelTrigger - Application

The time trigger only accepts values greater than or equal to 15; smaller values fail during Register.

C#

By default Windows 8 assumes that the background task is done after the Run method returns. However, if the Run method initiates asynchronous operations, it might return before all work has completed because there could still be inflight asynchronous operations. To facilitate asynchronous work associated with a background task, applications should use the BackgroundTaskDeferral class.

The Run method should request one BackgroundTaskDeferral per each asynchronous function call. The completion callback of each asynchronous operation should then call the Complete method of its BackgroundTaskDeferral instance.

 

sealed public class BackgroundClass : IBackgroundTask

{

    public void Run(IBackgroundTaskInstance taskInstance)

    {

        BackgroundTaskDeferral def1 = taskInstance.GetDeferral();

        IAsyncAction op1 = Something.DoAsync();

        op1.Completed = new AsyncActionCompletedHandler(

            (IAsyncAction act, AsyncStatus stat) =>

            {

                def1.Complete();

            });

 

        BackgroundTaskDeferral def2 = taskInstance.GetDeferral();

        IAsyncAction op2 = Something.DoAsync();

        op2.Completed = new AsyncActionCompletedHandler(

            (IAsyncAction act, AsyncStatus stat) =>

            {

                def2.Complete();

            });       

    }

}

In C#, the async/await language feature can be used, and the resulting syntax allows one single BackgroundTaskDeferral to be used even when there are multiple asynchronous operations involved. 

public sealed class TestClass:IBackgroundTask

{

    void async IBackgroundTask.Run(IBackgroundTaskInstance taskInstance)

    {

        BackgroundTaskDeferral deferral = taskInstance.GetDeferral();    

        await SomeOperationAsync();

        await SomeOtherOperationAsync();

        deferral.Complete();

    }

}

 

Java Script

The script can access the background task’s properties and events from the WebUIBackgroundTaskInstance object. A JavaScript background task must call Close after it has completed its work so that the task can be shut down.

(function()

{

    "use strict";

    var globalCount= 0,

    backgroundTask = Windows.UI.WebUIBackgroundTaskInstance.current;

 

    for (int i = 0; i < 10; i++)

    {

       globalCount += 10;

        backgroundTask.progress = globalCount;

    }

 

    backgroundTask.succeeded = true;

    close();

})();

 

 

    <Application Id="BackgroundTaskSample.App" Executable="BackgroundTaskSample.exe" EntryPoint="BackgroundTaskSample.App">

      <VisualElements DisplayName="BackgroundTaskSample" Logo="Images\squareTile-sdk.png" SmallLogo="Images\smallTile-sdk.png" Description="BackgroundTaskSample" ForegroundText="dark" BackgroundColor="#222222">

        <LockScreen Notification="badgeAndTileText" BadgeLogo="images\badgelogo.png" />

        <DefaultTile ShowName="allLogos" WideLogo="images\tile-sdk.png" />

        <SplashScreen Image="Images\splash-sdk.png" BackgroundColor="#FFFFFF" />

      </VisualElements>

      <Extensions>

        <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.SampleBackgroundTask">

          <BackgroundTasks>

            <Task Type="systemEvent" />

          </BackgroundTasks>

        </Extension>

        <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.ServicingComplete">

          <BackgroundTasks>

            <Task Type="systemEvent" />

          </BackgroundTasks>

        </Extension>

      </Extensions>

    </Application>

If an app is running and the user is interacting with the app in the foreground, then no CPU or Network resource constraints are applied to the app’s background tasks.

CPU resource constrains

Each app not on the lock screen receives 1 second of CPU time every 2 hours.

Network resource constraints

However, if a device is running on AC power then background tasks are not network constrained. CPU usage for a background task is always resource constrained even if the device is running on AC power.

Network resource constraints are a function of the amount of energy used by the network interface, which is modeled as the amount of time the network is used to transfer bytes (for download or upload); it is not based on any throughput metrics. The throughput and energy usage of a network interface varies based on factors like link capacity, physical position of the device, or the current load on the WiFi network. WiFi networks typically have lower energy consumption per byte sent and received when compared to cellular mobile networks.

 

Example network throughput for background tasks on DC with a WiFi network

Average throughput

Data throughput, in megabytes (MB)
for lock screen apps

Data throughput, in MB, for non-lock screen apps

 

Every 15 minutes

Per day

Every 2 hours

Per day

1 megabits per second (Mbps)

0.1875

18

0.25

3

10 Mbps

1.875

180

2.5

30

20 Mbps

3.75

360

5

60

Critical background tasks

Real-time applications like VOIP that rely on the Control Channel or Push Notification trigger may not want their critical background tasks to be suspended due to resource constraints in the middle of something important; for example,. an incoming call. Hence, background tasks that use the Control Channel or Push Notification trigger receive guaranteed application resource quotas (CPU and network) for every running task.

Global pool

Even with the assigned quota for each application, there will be scenarios where these fixed resource constraints may not be enough, and for those situations, there is a global pool from which applications can use CPU and network resources. The global pool is designed for rare instances where the guaranteed resources provided to apps are not enough and they need more CPU or network resources to complete their tasks. Apps should not rely on the availability of global pool because it’s a shared resource and other apps could have depleted the global pool. The global pool is replenished every 15 minutes at varying rates of refill depending on whether the computer is running on AC or DC power.

Registry keys to control global pool behavior

Value name

Type

Default value

Description

HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\BackgroundModel\Policy\CpuEnableGlobalPool

DWORD

1

Controls the CPU global pool. A value of zero disables CPU global pool.

HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\BackgroundModel\Policy\NetEnableGlobalPool

DWORD

1

Controls the network global pool. A value of zero disables network global pool.

If a background task is suspended because it has used its 2 seconds of CPU time and there are no resources in the global pool to use, a message is logged in the event viewer. A similar message is logged if the background task is suspended because it used all of its network resources and there are no network resources available in the global pool. In addition, the BackgroundTaskInstance class also has a SuspendedCount field that contains the number of times the background task has been suspended due to resource management constraints.

MaintenanceTrigger

Because the typical background task triggers are only allowed for apps on the lock screen, there is a need to run maintenance type tasks for apps not on the lock screen. This scenario is supported by the MaintenanceTrigger; these background tasks only run when the computer is running on AC power and are canceled when the computer transitions to DC (battery) power.

Background tasks triggered by MaintenanceTrigger must be hosted in BackgroundTaskHost.exe; that is, they can only run in BackgroundTaskHost.exe and not in the app executable.

MaintenanceTrigger can only run as long as the device is on AC power. All background tasks started by MaintenanceTrigger are canceled (with cancelReason = Abort) when the device transitions from AC to DC (battery). If the application does not cancel within 5 seconds of receiving the canceling event, the app is terminated.

The API contract for this class is the same as TimeTrigger. MaintenanceTrigger has a minimum period of 15 minutes, just like the TimeTrigger, and can only be triggered on the 15 minute boundary in an hour. This implies there are only 96 points of time in a day (60 mins/15 mins x 24) when the MaintenanceTrigger background task can run on a computer.

Brak komentarzy: