piątek, 20 stycznia 2012

Notatki o Windows 8 - odc. 24

Aplikacje Metro: migracja z aplikacji web i z Windows Phone 7, tworzenie komponentów Windows Runtime. Interesujące informacje z Windows Developer Preview Windows 8 guide na temat systemu operacyjnego.  Szczególnie polecam temat tasków w tle w aplikacjach Metro (z dodatkowego dokumentu Introduction to background tasks. Guidelines for developers, tych bardzo istotnych informacji nie ma jeszcze w dokumentacji MSDN).

Migrating a web app

The process that hosts and executes a Metro style app using JavaScript is called WWAHost.exe. This process provides a superset of functionality greater than that provided by the Microsoft Internet Explorer browser.

Libraries:

  • The Windows Library for JavaScript -- A toolkit of JavaScript libraries that support improved event handling and DOM query behaviors, enable new control types, and provide developer-friendly patterns for other common JavaScript behaviors.
  • Trident 6.0 -- An HTML- and CSS-based model for the layout and rendering of visual components that implements Canvas for the real-time drawing and manipulation of bitmap graphics, and Scalable Vector Graphics (SVG) support for vector graphics. (Trident 6.0 is the set of libraries used by Internet Explorer 10 for the display of content, and can be used to support additional graphics and rendering behaviors.)
  • The Windows Runtime -- Common APIs available to JavaScript by using the Windows Runtime infrastructure.

The WWAHost.exe provides an Internet Explorer-based rendering platform.

WWAHost.exe cannot host Adobe Flash Player, Microsoft Silverlight, Java objects most ActiveX controls and other embedded components. The following ActiveX controls are supported:

  • {88d96a05-f192-11d4-a65f-0040963251e5} XML DOM Document 6.0
  • {88d96a06-f192-11d4-a65f-0040963251e5} Free Threaded XML DOM Document 6.0
  • {88d96a07-f192-11d4-a65f-0040963251e5} XML Schema Cache 6.0
  • {88d96a08-f192-11d4-a65f-0040963251e5} XSL Template 6.0
  • {EE09B103-97E0-11CF-978F-00A02463E06F} Scripting.Dictionary
  • {B4644768-6186-4010-89AC-D6FD32CCD3E6} Testing Hook: Test Max Service
  • {FFC4E997-D97B-45DF-AD22-44C4B2DEDD2B} Testing Hook: Test WTT Logger
  • {186DD02C-2DEC-41B5-A7D4-B59056FADE51} PortableDeviceAutomation.Factory

Migrating a Windows Phone 7 app

Resolutions, input (WP7 touch oriented), phone-specific functionality in WP7, XNA to DirectX C++.

Note that the following Silverlight XAML namespaces do not have a direct analog in the Windows Runtime:

  • System.Windows.Automation.Text
  • System.Windows.Ink
  • System.Windows.Media.Effects
  • System.Windows.Messaging

Differences between Silverlight and Metro style apps using XAML:

  • Tiles have similar behaviors to Live Tiles in Windows Phone 7, although there are some differences.
  • Notifications are an extension of the push notification model in Windows Phone 7.

Creating Windows Runtime Components

With the .NET Framework 4.5 Developer Preview, you can use managed code to create your own Windows Runtime types, packaged in a Windows Runtime Component. Visual Studio makes it easy to add a C# or Visual Basic class library to your app, and to create Windows Runtime types that you can call from JavaScript. Internally, your Windows Runtime types can use any .NET Framework functionality that's allowed in a Metro style app. Externally, the members of your type can expose only Windows Runtime types for their parameters and return values. When you build your solution, Visual Studio builds your .NET Framework class library project and then executes a build step that creates a Windows Metadata (WinMD) file. This is your Windows Runtime Component, which Visual Studio includes in your app.

Visual Studio first compiles the class library, and then executes an MSBUILD task that runs the WinMdExp.exe utility to create the WinMD file, turning your class library into a Windows Runtime Component. The WinMD file contains both the managed code and the WinMD definitions that are used by JavaScript and the Windows Runtime. WinMdExp.exe generates build errors when you write code that's invalid in WinMD. Visual Studio adds your component to the package file (.appx) for your Metro style app, and generates the appropriate manifest.

The rules for managed WinMD and JavaScript

The .NET Framework contains many types that are not part of the Windows Runtime. You can use these types in the implementation of your Windows Runtime types, but they cannot be part of the public API surface. The following list describes the restrictions that are required by the Windows Runtime, and an additional restriction required by JavaScript.

  • The fields, parameters, and return values of all the public types and members in your component must be Windows Runtime types. In addition to types that are provided by the Windows Runtime itself, this includes the Windows Runtime types that you create. It also includes a number of .NET Framework types.
  • Classes and interfaces can contain methods, properties, and events. You can declare delegates for your events, or use the EventHandler<T> delegate. A class cannot:
    • Be generic.
    • Implement an interface that is not a Windows Runtime interface. (You can create your own Windows Runtime interfaces and implement them.)
    • Override methods of Object other than ToString.
    • Declare protected constructors.
  • All public types must have a root namespace that matches the assembly name, and the assembly name must not begin with "Windows".
  • Public structures can't have any members other than public fields, and those fields must be value types or strings.
  • To be usable from JavaScript, your classes must follow one more rule: You must declare them as sealed (NotInheritable in Visual Basic). This restriction does not apply to other consumers of WinMD libraries.

The following are known issues with managed Windows Runtime Components in Windows Developer Preview:

  • Each class in your component must have at least one instance member. Otherwise, the WinMdExp.exe utility can't create a class interface for it, and generates an error message to that effect.
  • You can't add events to the types in your component. If a class contains an event, attempting to instantiate the class from JavaScript results in "Unknown runtime error."
  • Some of the types that the .NET Framework appears to substitute for Windows Runtime types currently cannot be used as parameter types or return types of members in a component. Examples of these types include DateTimeOffset, TimeSpan, and Size. At run time, JavaScript reports a failure to load the type from the current assembly the first time the type is accessed. The corresponding Windows Runtime types cannot be used.
  • Visual Studio 11 Express for Windows Developer Preview fails to add classes to the app manifest if they don't have default constructors. This causes a "Class not registered" error at run time, when JavaScript code tries to instantiate the class. The workaround is to add a default constructor. When you encounter this error, simply adding a default constructor to the class doesn't fix the problem. Stop the debugger and then delete the AppXManifest.xml file from the Debug folder, forcing Visual Studio to regenerate the file and add the class. Alternatively, you can manually add the class to the extensions section of the manifest.
  • In Visual Studio 11 Express for Windows Developer Preview, the debugger doesn't show the correct members for some of the types that the .NET Framework appears to substitute for Windows Runtime types.
  • In Visual Studio 11 Express for Windows Developer Preview, the debugger is sometimes unable to obtain values for local variables. For example, in event handlers the parameters are frequently unavailable.

In Visual Studio 11 Express for Windows Developer Preview, you can't debug JavaScript and managed code at the same time.

In the .NET Framework, primitive types like the Int32 structure have many useful properties and methods, such as the Int32.TryParse method. By contrast, primitive types and structures in the Windows Runtime only have fields. When you pass these types to managed code, they appear to be .NET Framework types, and you can use the properties and methods of the .NET Framework types as you normally would.

You can tell when a Windows Runtime type appears as a .NET Framework type, because the IntelliSense in Visual Studio hides the Windows Runtime type when you're writing managed code, and presents the equivalent .NET Framework type.

Windows Developer Preview Windows 8 guide

Windows 8 has two touch keyboards for ultimate mobility and flexibility. An improved, full-sized touch
keyboard with larger buttons and a unique thumb keyboard make it easy to use your computer on the
go. Whether you’re walking around or sitting down, it’s more comfortable and natural to type using your
thumbs when the keyboard is split.

When you sign in with your connected Microsoft account to another PC running Windows 8, your Metro
style apps and settings go with you, so it’s just like you’re using your own PC. You’ll also be signed in to all
of the websites you were signed in to. Your connected account is like a portable, personal PC that appears
on any Windows 8-based PC you’re using.

Metro style apps run and stay up to date even when the PC is on standby. When you’re connected to the
Internet, you’ll receive information updates, email, VoIP calls, instant messages, and be able to stream
music or other content in the background. When Windows comes out of standby, your apps don’t need
time to catch up.

You can install your purchased apps on up to five Windows 8 PCs.

On x86 and x64 PCs, Windows 8 supports Windows 7 desktop applications and devices so you don’t have to
compromise or give up what you’re used to. On these PCs, your existing Windows 7-based applications just work.

Push-button reset

Windows 8 comes with a number of options to restore your PC to its original state. You can do a basic reset, which gives you an easy option to restart fresh while retaining all of your documents, accounts, personal settings, and even the apps you’ve downloaded from the Windows Store.

Windows 8 also provides some new, advanced options. You can do a complete reset, which restores the PC to
the state it was in when originally purchased. And you can also create a reset disk, which is great for power
users who have invested time to personalize and configure their PC. Restore from USB Key restores your PC
from a thumb drive, saving space and giving you a convenient backup tool.

Windows Update

If you turn on Windows Update during setup and your computer needs an update,
Windows can install it when you’re not using your computer or at a time you’ve specified. When an
update requires a reboot, there’s a grace period, allowing you to pick a time that’s convenient for you. As
a result, you see far fewer prompts about maintenance, updates, or reboots.

Windows Runtime

WinRT features are represented by the Application Binary Interface (ABI), which makes Windows APIs
accessible from other programming languages. The ABI is exposed in metadata assemblies (.winmd files),
allowing static languages (like C#) and dynamic languages (like JavaScript) to understand the structure of
the WinRT API.

Developing for IE 10

With the release of IE10, developers get even more support for HTML5, enabling them to create rich
visual effects and animations with hardware accelerated CSS transitions, animations, 3D transformations,
along with CSS3 text shadow, gradients, and SVG filter effects. Building increasingly sophisticated page
layouts is possible with support for CSS3 grid, flexible box layout, multi-column, figures, CSS3 regions, and
hyphenation, as well as HTML5 Forms and Input Controls.
The IE10 platform also includes support for local storage including IndexedDB, Application Cache, Async
scripts, Web Workers, ES5 Strict mode support, Web Sockets, HTML5 file APIs, drag-drop, history, and
sandboxing. These features give developers an increasingly sophisticated, standards-based, programming
model that is ideal for creating modern web experiences.

System requirements

Windows 8 works great on the same hardware that powers Windows Vista and Windows 7:

  • 1 gigahertz or faster 32-bit or processor
  • 1 gigabyte (GB) RAM (32-bit) or 2 GB RAM (64-bit)
  • 16 GB available hard disk space (32-bit) or 20 GB (64-bit)
  • DirectX 9 graphics device with WDDM 1.0 or higher driver

Of course, taking advantage of touch input requires a screen that supports multi-touch.

In addition to running on x86 and x64 devices, Windows 8 delivers even greater flexibility by running on
ARM devices. Depending on the technology you use, write your Metro style apps once and they can run on
any supported architecture.

Introduction to Background Tasks

Windows Developer Preview provides a number of features to make an app look alive with content even when the app is suspended:

  • Windows push notifications can be used to keep the app tile fresh and up-to-date.
  • Playback Manager can be used to play audio in the background.
  • The background transfer API can be used to download and upload files in the background.
  • File share contracts can be used to share data between apps.

Push notifications and the background transfer API are optimized for system performance and longer device battery life, so it’s best to use these features whenever possible. If a suspended app must run its own code to do other kinds of work, Windows Developer Preview provides apps with the ability to create background tasks.

Allowing apps to run code in the background when they are suspended is a powerful feature and is designed primarily for the real-time class of apps such as mail, VOIP, and chat apps. The background task execution environment is a restricted resource-managed environment and background tasks only receive a limited amount of CPU time. Background tasks should be used for small work items that have no interaction with the user and only provide limited service. Long running or expensive workloads in the background will deplete the user’s battery and are not an appropriate use for background tasks.

Scenarios that are appropriate for background tasks include downloading mail in the background, or showing a toast notification for an incoming VOIP call or a chat message, or reacting to a change in system condition (for example, UserAway) and updating the server with this information. Scenarios that are not appropriate for background tasks are indexing mail, transcoding photos, running SETI type workloads, or anything that requires user interaction through displaying UI or audio.

Real-time apps and the lock screen

To prevent abuse of system resources or excessive workloads that might drain the device battery, only apps that are on the lock screen are allowed to use background tasks. If an app that is not on the lock screen tries to access the time trigger or the real-time communication trigger, its background task will not be triggered.

image

If the user notices an app is running often and taking up too many resources in the Task Manager, the user can remove the app from the lock screen to prevent it from performing its background task activity. An app can register to be notified when it is added or removed from the lock screen by registering a background task with the LockScreenApplicationAdded or LockScreenApplicationRemoved triggers provided in the SystemTrigger class.

Terms and definitions

  • Background Task - a class implemented by the app to provide functionality even if the app is not in the foreground.
  • Background Trigger - a system-defined event that an app can associate with a background task. When the trigger is fired by the system, an app background task associated with the trigger is launched.
  • Background Condition - a set of zero or more conditions that need to be satisfied before the background task can run.
  • EntryPoint - the name of the class implementing the background task.
  • backgroundTaskHost.exe - a system-provided host executable to run the background task.

Background task architecture

A Metro style app registers its background tasks with the background task infrastructure by using the BackgroundTaskBuilder class. The background task is implemented as a class that implements the IBackgroundTask interface. This class name is specified in the TaskEntryPoint property of the BackgroundTaskBuilder class. The background task class is hosted in an in-proc server DLL which can be loaded in an app executable, as part of the app package, or in the system-provided backgroundTaskHost.exe.The background task can also be implemented as a JavaScript worker. The JavaScript worker is included in the app as a JavaScript file and the name of the JavaScript file is specified in the TaskEntryPoint property of the BackgroundTaskBuilder class. The JavaScript worker runs in the system-provided WWA host process similar to a web worker.

A background task must have exactly one trigger that describes the trigger event to launch the background task. The trigger is specified with the SetTrigger method of the BackgroundTaskBuilder class.

Background task trigger events

  • InternetAvailable
  • InternetNotAvailable
  • LockScreenApplicationAdded  - an app tile is added to the lock screen.
  • LockScreenApplicationRemoved
  • NetworkNotificationChannelReset
  • NetworkStateChange - a network change such as a change in cost or connectivity occurs.
  • ServicingComplete - the system has finished updating an application.
  • SessionConnected
  • SessionDisconnected
  • SessionStart - the user session starts
  • SmsReceived
  • TimeTrigger
  • TimeZoneChange
  • UserAway
  • UserPresent

A background task can optionally have one or more conditions that must be true for the task to launch. Background conditions are used by an app to describe the set of conditions required to perform meaningful work. For example, if the background task requires the Internet but there is not currently an Internet connection, an InternetAvailable condition can be used to tell the system to wait for the Internet connection to be restored before launching the background task. Background conditions are specified with the AddCondition method of the BackgroundTaskBuilder class.

Background task conditions

  • InternetAvailable
  • InternetNotAvailable
  • SessionConnected
  • SessionDisconnected
  • UserNotPresent
  • UserPresent

Background task infrastructure

When the trigger is fired, the background task infrastructure launches the class associated with the trigger regardless of the state of the app. The activation of the background task does not involve any UI and it does not bring the Metro style app to the foreground. The triggers provided in the system are timer, system event and real-time communication.

image

When the trigger is fired, the system infrastructure activates the class within the app container.

Background tasks and the Metro style app lifecycle

When a background task is launched, an app can be in any of the following states: Running, Terminated or Suspended. If an app is in the Running state, it is the only app in the foreground. If an app is not running, it is in either the Suspended or Terminated state. A suspended app is resident in memory, but its work is not being scheduled by the system. A terminated app is not in memory, either because it was never launched or because it was in the Suspended state and was terminated by the system.

The background task executes in either the system-provided backgroundTaskHost.exe or the app process. The app specifies the execution host in its manifest.

If a background task executes in the system-provided backgroundTaskHost.exe, it is launched independently of the state of the app; it is not necessary for the system to change the app’s state. This option is preferable because launching the task within backgroundTaskHost.exe is faster and provides better performance than launching the background task within the app. BackgroundTaskHost.exe is launched within the same app container as the app and it terminates after the background tasks finish.

If a background task executes within the app process, the background task infrastructure might need to change the state of the app:

  • Running: If the app is running, it is already in the foreground and the background task is simply launched within the app.
  • Suspended: If the app is suspended, most of its threads are unfrozen and the background task is launched.
  • Terminated: If the app is terminated, it is not running at the time of the trigger so the app is activated and the background task is run. The app activation does not involve UI and it does not bring the app to the foreground.

Background task implementation concepts

All background task registrations are persistent; that is, the app doesn’t have to be running for the background task to be triggered. For example, if a background task should run 6 hours from now to download RSS feeds, the app registers the background task using TimeTrigger with the appropriate value. When the time arrives, the background task is launched regardless of whether the app is running or the machine has been restarted since the task was registered.

Condition latching behavior

When a trigger is fired, the background task infrastructure checks whether all the conditions are satisfied. If not, the infrastructure waits until all the conditions are satisfied before executing the background task. This behavior is called latching, because the background task infrastructure latches the trigger to a fired state.

If a condition changes value while a trigger is latched, the background task infrastructure re-checks to see if the conditions are satisfied for the background task. If so, it launches the task.

Background task progress reporting

The background task can use the progress handler to report progress to the app when the app is running in the foreground. The progress reported from the background task can be used to display UI or a progress bar in the foreground app.

The IBackgroundTaskInstance that is passed to the Run method is used to communicate progress to the foreground app. The interface has a Progress property which can be updated by the background task. 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 Suspended or Terminated.

Background task completion notification

The foreground app can also register a completion handler to be notified when the background task completes. The completion status or any exception thrown in the Run method of the background task is passed to the completion handler in the foreground app as part of the BackgroundTaskCompletedEventArgs input parameter. If the app is in the Suspended or Terminated state, it does not receive the completion notification. If the background task needs to preserve the information that it ran successfully, it must persist the information using State Manager or another means such as a file that the app can read when it comes back to the Running state.

Background task cancellation

Background tasks can be cancelled by the system in certain conditions. To receive cancellation notifications, the app’s background tasks should register a cancellation using the IBackgroundTaskInstance. When the system cancels a background task, it provides a reason in the BackgroundTaskCancellationReason parameter of the BackgroundTaskCanceledEventHandler.

If the background task does not respond to the cancellation notification and return from its background task within five (5) seconds, the app is terminated. To ensure a graceful exit and the guarantee that state is saved, apps are encouraged to register a cancellation handler and save state and exit the background task in response to a cancellation request.

Background task enumeration and re-associating handlers

When a Metro style app is launched from the Terminated state, it can enumerate all background tasks it has registered with the system using the BackgroundTaskRegistration.AllTasks method. Because the app has just been launched, it must re-associate its progress and completion handlers with the background tasks. Even if the app has previously registered those associations, they are no longer valid because the app was terminated and removed from memory. Only the progress and completion handlers must be re-associated. The background task registrations themselves are persistent.

The progress and completion handlers are event delegates or functions and are not defined in the manifest as are the class names (EntryPoint), which is why they need to be associated after the app has been launched.

If the app was resumed from the Suspended state then it does not have to re-associate its progress and completion handlers for its background tasks. They remain valid, because a suspended app remains in memory.

foreach (var task in BackgroundTaskRegistration.AllTasks)

{

    task.Value.Progress += new BackgroundTaskProgressEventHandler(OnProgress);

    task.Value.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);

}

var iter = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks.first();

var hascur = iter.hasCurrent;

while (hascur)

{

    var cur = iter.current.value   

    cur.addEventListener("progress", onProgress);

    cur.addEventListener("completed", onCompleted);

    hascur = iter.moveNext();

}

App updates or servicing

Background task registrations persist across app updates. If an app is updated, its registrations continue to be valid and will be triggered. The app developer must ensure that the background task EntryPoint still exists in the updated version of the class, otherwise the background task will error out during activation. To delete a previous background task registration upon update, an app can register a background task for a ServicingComplete trigger to be notified when the app is updated, and unregister background tasks that are no longer valid.

Sample background task

private void RegisterBackgroundTasks()

{

    BackgroundTaskBuilder builder = new BackgroundTaskBuilder();

    builder.Name = "BackgroundTestClass";       // Friendly string name identifying the background task

    builder.TaskEntryPoint = "BackgroundTaskLibrary.TestClass";     // Class name

    IBackgroundTrigger trigger = new TimeTrigger(15, true);

    builder.SetTrigger(trigger);

    IBackgroundCondition condition = new SystemCondition(SystemConditionType.InternetAvailable);

    builder.AddCondition(condition);

 

    IBackgroundTaskRegistration task = builder.Register();

               

    task.Progress += new BackgroundTaskProgressEventHandler(task_Progress);

    task.Completed += new BackgroundTaskCompletedEventHandler(task_Completed);

}

function RegisterSampleBackgroundTaskWithCondition()

{

    var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();

    builder.name = "BackgroundTestWorker";

    builder.taskEntryPoint = "BackgroundTestWorker.js";    

    var myTrigger = new Windows.ApplicationModel.Background.TimeTrigger(15, true);

    builder.setTrigger(myTrigger);       

    var condition = new Windows.ApplicationModel.Background.SystemCondition(Windows.ApplicationModel.Background.SystemConditionType.internetAvailable);

    builder.addCondition(condition);

 

    var task = myTaskBuilder.register();

 

    task.addEventListener("progress", task_Progress);

    task.addEventListener("completed", task_Completed);

}

Background task class

C#

BackgroundTaskLibrary.TestClass implements the IBackgroundTask interface that has a Run method. The Run method is where the actual background task code exists. The class implementing IBackgroundTask interface must be sealed. The Run method receives IBackgroundTaskInstance as an input parameter which contains information about the task (trigger and conditions).

namespace BackgroundTaskLibrary

{

    public sealed class TestClass:IBackgroundTask

    {

        private int globalcount;

 

        void IBackgroundTask.Run(IBackgroundTaskInstance taskInstance)

        {

            globalcount = 0;

 

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

            {

                Interlocked.Increment(ref globalcount);

                taskInstance.Progress = (uint)globalcount;

            }

        }

    }

}

JavaScript

BackgroundTestWorker.js is a JavaScript file included with the app. The script in this file runs when the background task is triggered. The script can access IBackgroundTaskInstance through the WebUIApplication object as a static property. 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.WebUI.WebUIApplication.backgroundTask;

 

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

    {

       globalCount += 10;

        backgroundTask.taskInstance.progress = globalCount;

    }

 

    backgroundTask.success = true;

    close();

})();

Adding a background task to a solution

To add a C# class library implementing the IBackgroundTask interface to your project, follow these steps:

  • Add a new Windows Metro style app class library project to the solution.
  • Modify the class library project properties so that it outputs a winmd instead of a DLL.
  • Add a reference to the newly added class library project in the main Windows Metro style app project that registers the background tasks.
  • Add the required manifest entries for background tasks to the Windows Metro style app project (not the class library).

To add a JavaScript background worker to your project, add a new dedicated worker file.

Background task sample manifest

Metro style apps must be manifested to use background task extension contracts. Every Metro style app has an associated manifest that is used by the app to indicate it is using the background task extension contract. An app’s manifest can contain multiple background task extensions with different class names (EntryPoint) or JavaScript files, executable, or task types within the same app.

<Package>

  <Applications>

    <Application Id="App" Executable="application2.exe" EntryPoint="Application2.App">

      <VisualElements DisplayName="Application2" Logo="Images\Logo.png" SmallLogo="Images\SmallLogo.png" Description="Application2" ForegroundText="light" BackgroundColor="#222222" InitialRotationPreference="portrait">

        <SplashScreen Image="Images\SplashScreen.png" />

      </VisualElements>

      <Extensions>

        <Extension Category="windows.backgroundTasks" Executable="backgroundTaskHost.exe" EntryPoint="BackgroundTaskLibrary.TestClass">

          <BackgroundTasks>

            <Task Type="timer" />

            <Task Type="systemEvent" />

          </BackgroundTasks>

        </Extension>

      </Extensions>

    </Application>

  </Applications>

  <Capabilities>

    <Capability Name="internetClient" />

  </Capabilities>

</Package>

If the manifest does not specify an executable, then the executable is the same as the app executable.

<Package>

  <Applications>

    <Application Id="App" StartPage="default.html ">

      <VisualElements DisplayName="Application2" Logo="Images\Logo.png" SmallLogo="Images\SmallLogo.png" Description="Application2" ForegroundText="light" BackgroundColor="#222222" InitialRotationPreference="portrait">

        <SplashScreen Image="Images\SplashScreen.png" />

      </VisualElements>

      <Extensions>

        <Extension Category="windows.backgroundTasks" StartPage="BackgroundTestWorker.js">

          <BackgroundTasks>

            <Task Type="timer" />

            <Task Type="systemEvent" />

          </BackgroundTasks>

        </Extension>

      </Extensions>

    </Application>

  </Applications>

  <Capabilities>

    <Capability Name="internetClient" />

  </Capabilities>

</Package>

The extension must specify the triggers used by the class or JavaScript file. If the trigger type is not specified correctly, the Register operation fails.

Background task resource management

Background tasks are meant to be short-lived tasks that do not consume a lot of resources. If an app is running and the user is interacting with the app in the foreground, then no CPU quota or resource management policies are applied to the app’s background tasks.

An app on the lock screen receives a certain amount of CPU time at regular intervals for its background tasks. If the app uses all of its available CPU time, its background tasks are suspended until the app’s CPU quota is replenished at the next generation for CPU quota updates.

Each app on the lock screen receives two seconds of CPU time every 15 minutes which can be utilized by all of the background tasks of the app. At the end of 15 minutes, each app on the lock screen receives another two seconds of CPU time for use by its background tasks. Any unused CPU time in the 15-minute interval is lost and not accumulated by the app. If a background task is suspended because it has used its two seconds of CPU time, the message ‘Background work item for package “” with entry point “” was throttled by sandboxing policy’ is logged in the event viewer.

CPU usage time refers to the amount of actual CPU used by the app and not the wall clock time of the background task. For example, if the background task is waiting in its code for the remote server to respond and not actually using the CPU, then the wait time is not counted against the CPU quota because the background task is not using the CPU. CPU usage information is available in Task Manager or more sophisticated tools like xperf, which is available in the Windows Performance Tools (WPT) Kit.

The reason for using CPU usage as a unit of resource management instead of total running time or wall clock time is because that is a more fair metric for measuring actual energy usage of an app. If an app is not using the CPU and might be waiting for input, the CPU could go to a low power state, conserving battery life.

Threading model for background tasks hosted in the app

If background tasks authored in C# or C++ are hosted within the app instead of the recommended backgroundTaskHost.exe, there are some threading model complexities to keep in mind.

Decoupling the background task from the app

For non-JavaScript apps, the background tasks are hosted in an in-proc DLL which is loaded in a multi-threaded apartment (MTA) within the app. For JavaScript apps, background tasks are launched in a new single-threaded apartment (STA) within the WWA host process. The actual background task class can be STA or MTA. Because background tasks can run when an app is in a Suspended or Terminated state, they need to be decoupled from the foreground app. Loading the background task DLL in a separate apartment enforces separation of the background task from the app while allowing the background task to be controlled independently of the app.

When an app is suspended, the UI STA thread is blocked in the Windows kernel. This thread is released only when the app transitions back to a Running state in response to user interaction. When the app is in the background and a background task is triggered, all threads in the app except the UI STA thread are unfrozen and the background task is activated in an MTA thread. The UI STA thread remains blocked. If the background task tries to access an object that is owned by the blocked UI STA thread, then it will deadlock. To prevent this deadlock, the background task should not share data between the app and the background task.

Sharing state between the background task and the foreground app

Another aspect to keep in mind if the background task is loaded within the app instead of the recommended backgroundTaskHost.exe is that it cannot rely on accessing memory of the foreground app. Background tasks run regardless of the current state of the app, so background tasks cannot rely on having the app around when they run. The only reliable way for the background task to share state with the app is to use persistent storage such as State Manager or files.

Background task best practices

When using background tasks in your app, follow these best practices:

  • Design background tasks to be short lived.
  • Use backgroundTaskHost.exe as the executable for background tasks.
  • Describe the background task class name or JavaScript file name accurately in the manifest.
  • Use persistent storage to share data between the background task and the app.
  • Register for progress and completion handlers in the app.
  • Register for a background task cancellation handler in the background task class.
  • Register for the ServicingComplete trigger if you expect to update the app.
  • Ensure the C# class library output is a winmd file instead of a DLL.
  • Describe the triggers in the background manifest accurately.

Avoid the following:

  • Do not display UI other than toast notifications from a background task.
  • Do not rely on user interaction in background tasks.

c.d.n

Brak komentarzy: