C#または Visual Basic Windows ランタイムコンポーネントを作成し、JavaScript から呼び出す方法に関するチュートリアルWalkthrough of creating a C# or Visual Basic Windows Runtime component, and calling it from JavaScript

このチュートリアルでは、Visual Basic またはC#で .net を使用して、Windows ランタイムコンポーネントにパッケージ化された独自の Windows ランタイム型を作成する方法、および JavaScript ユニバーサル WINDOWS プラットフォーム (UWP) アプリからそのコンポーネントを呼び出す方法について説明します。This walkthrough shows how you can use .NET with Visual Basic or C# to create your own Windows Runtime types, packaged in a Windows Runtime component, and how then to call that component from a JavaScript Universal Windows Platform (UWP) app.

Visual Studio を使用C#すると、または Visual Basic で記述された Windows ランタイムコンポーネント (WRC) プロジェクト内に独自のカスタム Windows ランタイム型を簡単に作成して配置し、JavaScript アプリケーションプロジェクトからその WRC を参照して、それらを使用することができます。そのアプリケーションからのカスタム型。Visual Studio makes it easy to author and deploy your own custom Windows Runtime types inside a Windows Runtime component (WRC) project written with C# or Visual Basic, and then to reference that WRC from a JavaScript application project, and to consume those custom types from that application.

内部的には、Windows ランタイム型は、UWP アプリケーションで許可されているすべての .NET 機能を使用できます。Internally, your Windows Runtime types can use any .NET functionality that's allowed in a UWP application.

外部的には、型のメンバーは、パラメーターと戻り値に対して Windows ランタイム型のみを公開できます。Externally, the members of your type can expose only Windows Runtime types for their parameters and return values. ソリューションをビルドすると、Visual Studio によって .NET WRC プロジェクトがビルドされ、Windows メタデータ (winmd) ファイルを作成するビルドステップが実行されます。When you build your solution, Visual Studio builds your .NET WRC project, and then executes a build step that creates a Windows metadata (.winmd) file. これが、Visual Studio がアプリに含める Windows ランタイム コンポーネントです。This is your Windows Runtime component, which Visual Studio includes in your app.

注意

.NET では、プリミティブデータ型やコレクション型などの一般的に使用される .NET 型が、同等の Windows ランタイムに自動的にマップされます。.NET automatically maps some commonly used .NET types, such as primitive data types and collection types, to their Windows Runtime equivalents. これらの .NET 型は、Windows ランタイムコンポーネントのパブリックインターフェイスで使用できます。また、コンポーネントのユーザーには、対応する Windows ランタイムの種類として表示されます。These .NET types can be used in the public interface of a Windows Runtime component, and will appear to users of the component as the corresponding Windows Runtime types. 「」および「 C# Visual Basic によるコンポーネントの Windows ランタイム」を参照してください。See Windows Runtime components with C# and Visual Basic.

前提条件:Prerequisites:

単純な Windows ランタイム クラスの作成Creating a simple Windows Runtime class

このセクションでは、JavaScript UWP アプリケーションを作成し、Visual Basic またはC# Windows ランタイムコンポーネントプロジェクトをソリューションに追加します。This section creates a JavaScript UWP application, and adds to the solution a Visual Basic or C# Windows Runtime component project. Windows ランタイム型を定義する方法、JavaScript から型のインスタンスを作成する方法、および静的メンバーとインスタンスメンバーを呼び出す方法を示します。It shows how to define a Windows Runtime type, create an instance of the type from JavaScript, and call static and instance members. コンポーネントにフォーカスを保持するために、サンプルアプリのビジュアル表示は意図的に低キーです。The visual display of the example app is deliberately low-key in order to keep the focus on the component.

  1. Visual Studio で新しい JavaScript プロジェクトを作成します。メニュー バーで、 [ファイル]、[新規作成]、[プロジェクト] の順にクリックします。In Visual Studio, create a new JavaScript project: On the menu bar, choose File, New, Project. [新しいプロジェクト] ダイアログ ボックスの [インストールされたテンプレート] セクションで [JavaScript] を選択し、 [Windows][ユニバーサル] の順に選択しますIn the Installed Templates section of the New Project dialog box, choose JavaScript, and then choose Windows, and then Universal. ([Windows] が利用できない場合は、Windows 8 以降を使っていることを確認してください)。 [新しいアプリケーション] テンプレートを選び、プロジェクト名として「SampleApp」と入力します。(If Windows is not available, make sure you're using Windows 8 or later.) Choose the Blank Application template and enter SampleApp for the project name.

  2. コンポーネント プロジェクトを作成します。ソリューション エクスプローラーで、SampleApp ソリューションのショートカット メニューを開き、 [追加][新しいプロジェクト] の順にクリックして、新しい C# プロジェクトまたは Visual Basic プロジェクトをソリューションに追加します。Create the component project: In Solution Explorer, open the shortcut menu for the SampleApp solution and choose Add, and then choose New Project to add a new C# or Visual Basic project to the solution. [新しいプロジェクトの追加] ダイアログ ボックスの [インストールされたテンプレート] セクションで、 [Visual Basic] または [Visual C#] を選択し、 [Windows][ユニバーサル] の順に選択します。In the Installed Templates section of the Add New Project dialog box, choose Visual Basic or Visual C#, and then choose Windows, and then Universal. [Windows ランタイム コンポーネント] テンプレートを選択し、プロジェクト名として「SampleComponent」と入力します。Choose the Windows Runtime Component template and enter SampleComponent for the project name.

  3. クラス名を「Example」に変更します。Change the name of the class to Example. 既定では、クラスは public sealed (Visual Basic では Public NotInheritable) としてマークされていることに注意してください。Notice that by default, the class is marked public sealed (Public NotInheritable in Visual Basic). コンポーネントから公開するすべての Windows ランタイム クラスをシールする必要があります。All the Windows Runtime classes you expose from your component must be sealed.

  4. static メソッド (Visual Basic では Shared メソッド) とインスタンス プロパティの 2 つの単純なメンバーをクラスに追加します。Add two simple members to the class, a static method (Shared method in Visual Basic) and an instance property:

    namespace SampleComponent
    {
        public sealed class Example
        {
            public static string GetAnswer()
            {
                return "The answer is 42.";
            }
    
            public int SampleProperty { get; set; }
        }
    }
    
    Public NotInheritable Class Example
        Public Shared Function GetAnswer() As String
            Return "The answer is 42."
        End Function
    
        Public Property SampleProperty As Integer
    End Class
    
  5. 省略可能: 新しく追加したメンバーで IntelliSense を有効にするには、ソリューション エクスプローラーで SampleComponent プロジェクトのショートカット メニューを開き、 [ビルド] を選びます。Optional: To enable IntelliSense for the newly added members, in Solution Explorer, open the shortcut menu for the SampleComponent project, and then choose Build.

  6. ソリューション エクスプローラーの JavaScript プロジェクトで、 [参照] のショートカット メニューを開き、 [参照の追加] をクリックして [参照マネージャー] を開きます。In Solution Explorer, in the JavaScript project, open the shortcut menu for References, and then choose Add Reference to open the Reference Manager. [プロジェクト] をクリックし、 [ソリューション] をクリックします。Choose Projects, and then choose Solution. SampleComponent プロジェクトのチェック ボックスをオンにし、 [OK] をクリックして参照を追加します。Select the check box for the SampleComponent project and choose OK to add a reference.

JavaScript からコンポーネントを呼び出すCall the component from JavaScript

JavaScript から Windows ランタイム型を使うには、(プロジェクトの js フォルダーにある) default.js ファイルで、Visual Studio テンプレートで提供される匿名関数に次のコードを追加します。To use the Windows Runtime type from JavaScript, add the following code in the anonymous function in the default.js file (in the js folder of the project) that is provided by the Visual Studio template. 匿名関数は、app.oncheckpoint イベント ハンドラーの後の app.start 呼び出しの前にあります。It should go after the app.oncheckpoint event handler and before the call to app.start.

var ex;

function basics1() {
   document.getElementById('output').innerHTML =
        SampleComponent.Example.getAnswer();

    ex = new SampleComponent.Example();

   document.getElementById('output').innerHTML += "<br/>" +
       ex.sampleProperty;

}

function basics2() {
    ex.sampleProperty += 1;
    document.getElementById('output').innerHTML += "<br/>" +
        ex.sampleProperty;
}

各メンバー名の最初の文字が大文字から小文字に変更されていることに注意してください。Notice that the first letter of each member name is changed from uppercase to lowercase. この変換は、Windows ランタイムの自然な使い方を可能にするために JavaScript が提供するサポートの一部です。This transformation is part of the support that JavaScript provides to enable the natural use of the Windows Runtime. 名前空間とクラス名は pascal 規約に従って大文字小文字が使い分けられます。Namespaces and class names are Pascal-cased. すべて小文字のイベント名を除き、メンバー名は camel 規約に従っています。Member names are camel-cased except for event names, which are all lowercase. JavaScript での Windows ランタイムの使用」をご覧ください。See Using the Windows Runtime in JavaScript. camel 規約の規則はわかりにくい場合があります。The rules for camel casing can be confusing. 通常、一連の先頭の大文字は小文字で表示されますが、3 つの大文字の後に小文字が続く場合は、最初の 2 つの文字だけが小文字で表示されます。たとえば、IDStringKind という名前のメンバーは idStringKind と表示されます。A series of initial uppercase letters normally appears as lowercase, but if three uppercase letters are followed by a lowercase letter, only the first two letters appear in lowercase: for example, a member named IDStringKind appears as idStringKind. Visual Studio では、Windows ランタイム コンポーネント プロジェクトをビルドし、JavaScript プロジェクトで IntelliSense を使って正しい大文字小文字の区別を確認できます。In Visual Studio, you can build your Windows Runtime component project and then use IntelliSense in your JavaScript project to see the correct casing.

同様に、.NET では、マネージコードでの Windows ランタイムの自然な使用を有効にすることがサポートされています。In similar fashion, .NET provides support to enable the natural use of the Windows Runtime in managed code. この点については、この記事の後続のセクションで説明しています。また、 C#と Visual Basicおよび .net でのUWP アプリと Windows ランタイムに対する .net のサポートについては、これらの記事を Windows ランタイム。This is discussed in subsequent sections of this article, and in the articles Windows Runtime components with C# and Visual Basic and .NET support for UWP apps and the Windows Runtime.

単純なユーザー インターフェイスを作成するCreate a simple user interface

JavaScript プロジェクトで、default.html ファイルを開き、次のコードに示すように本文を更新します。In your JavaScript project, open the default.html file and update the body as shown in the following code. このコードには、サンプル アプリのコントロールの完全なセットが含まれています。また、クリック イベントの関数名も指定されています。This code includes the complete set of controls for the example app and specifies the function names for the click events.

メモアプリを最初に実行する   When、Basics1 と Basics2 のボタンのみがサポートされています。Note  When you first run the app, only the Basics1 and Basics2 button are supported.

<body>
            <div id="buttons">
            <button id="button1" >Basics 1</button>
            <button id="button2" >Basics 2</button>

            <button id="runtimeButton1">Runtime 1</button>
            <button id="runtimeButton2">Runtime 2</button>

            <button id="returnsButton1">Returns 1</button>
            <button id="returnsButton2">Returns 2</button>

            <button id="events1Button">Events 1</button>

            <button id="btnAsync">Async</button>
            <button id="btnCancel" disabled="disabled">Cancel Async</button>
            <progress id="primeProg" value="25" max="100" style="color: yellow;"></progress>
        </div>
        <div id="output">
        </div>
</body>

JavaScript プロジェクトで、css フォルダーの default.css を開きます。In your JavaScript project, in the css folder, open default.css. body セクションを次のように変更し、ボタンのレイアウトと出力テキストの配置を制御するスタイルを追加します。Modify the body section as shown, and add styles to control the layout of buttons and the placement of output text.

body
{
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr 14fr;
    display: -ms-grid;
}

#buttons {
    -ms-grid-rows: 1fr;
    -ms-grid-columns: auto;
    -ms-grid-row-align: start;
}
#output {
    -ms-grid-row: 2;
    -ms-grid-column: 1;
}

次に、default.js で app.onactivated 内の processAll 呼び出しに then 句を追加して、イベント リスナーの登録コードを追加します。Now add the event listener registration code by adding a then clause to the processAll call in app.onactivated in default.js. setPromise を呼び出す既存のコード行を置き換え、次のコードに変更します。Replace the existing line of code that calls setPromise and change it to the following code:

args.setPromise(WinJS.UI.processAll().then(function () {
    var button1 = document.getElementById("button1");
    button1.addEventListener("click", basics1, false);
    var button2 = document.getElementById("button2");
    button2.addEventListener("click", basics2, false);
}));

HTML コントロールにイベントを追加するときは、HTML でクリック イベント ハンドラーを直接追加するのではなく、この方法をお勧めします。This is a better way to add events to HTML controls than adding a click event handler directly in HTML. Hello, World "アプリ (JS) を作成する」を参照してください。See Create a "Hello, World" app (JS).

アプリをビルドして実行するBuild and run the app

ビルドする前に、お使いのコンピューターに応じて、すべてのプロジェクトのターゲット プラットフォームを ARM、x64、または x86 に変更します。Before you build, change the target platform for all projects to ARM, x64, or x86, as appropriate for your computer.

ソリューションをビルドして実行するには、F5 キーを押しますTo build and run the solution, choose the F5 key. (SampleComponent が未定義であることを示す実行時エラー メッセージが表示された場合は、クラス ライブラリ プロジェクトへの参照がありません)。(If you get a run-time error message stating that SampleComponent is undefined, the reference to the class library project is missing.)

Visual Studio では、まずクラス ライブラリをコンパイルし、Winmdexp.exe (Windows ランタイム メタデータ エクスポート ツール) を実行する MSBuild タスクを実行して、Windows ランタイム コンポーネントを作成します。Visual Studio first compiles the class library, and then executes an MSBuild task that runs Winmdexp.exe (Windows Runtime Metadata Export Tool) to create your Windows Runtime component. コンポーネントは、マネージ コードと、コードを説明する Windows メタデータの両方を含む .winmd ファイルに含まれています。The component is included in a .winmd file that contains both the managed code and the Windows metadata that describes the code. Windows ランタイム コンポーネントで無効なコードを作成した場合、WinMdExp.exe によってビルド エラー メッセージが生成され、Visual Studio IDE に表示されます。WinMdExp.exe generates build error messages when you write code that's invalid in a Windows Runtime component, and the error messages are displayed in the Visual Studio IDE. Visual Studio によって、コンポーネントが UWP アプリケーションのアプリケーションパッケージ (.appx ファイル) に追加され、適切なマニフェストが生成されます。Visual Studio adds your component to the app package (.appx file) for your UWP application, and generates the appropriate manifest.

[Basics 1] ボタンをクリックして GetAnswer 静的メソッドからの戻り値を出力領域に割り当て、Example クラスのインスタンスを作成し、SampleProperty プロパティの値を出力領域に表示します。Choose the Basics 1 button to assign the return value from the static GetAnswer method to the output area, create an instance of the Example class, and display the value of its SampleProperty property in the output area. 出力は次のように表示されます。The output is shown here:

"The answer is 42."
0

[Basics 2] ボタンをクリックして SampleProperty プロパティの値を増やし、新しい値を出力領域に表示します。Choose the Basics 2 button to increment the value of the SampleProperty property and to display the new value in the output area. 文字列や数値などのプリミティブ型は、パラメーターの型や戻り値の型として使用でき、マネージ コードと JavaScript の間で渡すことができます。Primitive types such as strings and numbers can be used as parameter types and return types, and can be passed between managed code and JavaScript. JavaScript の数値は倍精度浮動小数点形式で保存されるため、.NET Framework の数値型に変換されます。Because numbers in JavaScript are stored in double-precision floating-point format, they are converted to .NET Framework numeric types.

メモ  By 既定では、JavaScript コードでのみブレークポイントを設定できます。Note  By default, you can set breakpoints only in your JavaScript code. Visual Basic またはコードをC#デバッグするには、「」 C#および「Visual Basic で Windows ランタイムコンポーネントを作成する」を参照してください。To debug your Visual Basic or C# code, see Creating Windows Runtime components in C# and Visual Basic.

デバッグを停止してアプリを閉じるには、アプリから Visual Studio に切り替え、Shift キーを押しながら F5 キーを押します。To stop debugging and close your app, switch from the app to Visual Studio, and choose Shift+F5.

JavaScript とマネージ コードからの Windows ランタイムの使用Using the Windows Runtime from JavaScript and managed code

Windows ランタイムは、JavaScript またはマネージ コードから呼び出すことができます。The Windows Runtime can be called from either JavaScript or managed code. Windows ランタイム オブジェクトはこの 2 つの間で受け渡すことができ、イベントはどちらの側からでも処理できます。Windows Runtime objects can be passed back and forth between the two, and events can be handled from either side. ただし、2つの環境の Windows ランタイム型を使用する方法は、いくつかの詳細に違いがあります。これは、JavaScript と .NET では Windows ランタイムが異なる方法でサポートされるためです。However, the ways you use Windows Runtime types in the two environments differ in some details, because JavaScript and .NET support the Windows Runtime differently. 次の例では、Windows.Foundation.Collections.PropertySet クラスを使用して、これらの違いを示します。The following example demonstrates these differences, using the Windows.Foundation.Collections.PropertySet class. この例では、マネージ コードで PropertySet コレクションのインスタンスを作成し、コレクションの変更を追跡するイベント ハンドラーを登録します。In this example, you create an instance of the PropertySet collection in managed code and register an event handler to track changes in the collection. 次に、コレクションを取得し、独自のイベント ハンドラーを登録して、コレクションを使用する JavaScript コードを追加します。Then you add JavaScript code that gets the collection, registers its own event handler, and uses the collection. 最後に、マネージ コードからコレクションに変更を加え、マネージ例外を処理する JavaScript を示すメソッドを追加します。Finally, you add a method that makes changes to the collection from managed code and shows JavaScript handling a managed exception.

重要  In この例では、UI スレッドでイベントが発生しています。Important  In this example, the event is being fired on the UI thread. 非同期呼び出しなどでバックグラウンド スレッドからイベントを発生させる場合は、JavaScript がそのイベントを処理できるように、追加の作業が必要になります。If you fire the event from a background thread, for example in an async call, you will need to do some extra work in order for JavaScript to handle the event. 詳細については、「 Windows ランタイムコンポーネントでのイベントの発生」を参照してください。For more information, see Raising Events in Windows Runtime components.

SampleComponent プロジェクトで、PropertySetStats という名前の新しい public sealed クラス (Visual Basic では Public NotInheritable クラス) を追加します。In the SampleComponent project, add a new public sealed class (Public NotInheritable class in Visual Basic) named PropertySetStats. このクラスは、PropertySet コレクションをラップし、MapChanged イベントを処理します。The class wraps a PropertySet collection and handles its MapChanged event. イベント ハンドラーは発生した各種変更の数を追跡し、DisplayStats メソッドは HTML 形式のレポートを生成します。The event handler tracks the number of changes of each kind that occur, and the DisplayStats method produces a report that is formatted in HTML. 追加の using ステートメント (Visual Basic では Imports ステートメント) に注意してください。このステートメントで既存の using ステートメントを上書きするのではなく、このステートメントを既存の using ステートメントに追加する必要があります。Notice the additional using statement (Imports statement in Visual Basic); be careful to add this to the existing using statements rather than overwriting them.

using Windows.Foundation.Collections;

namespace SampleComponent
{
    public sealed class PropertySetStats
    {
        private PropertySet _ps;
        public PropertySetStats()
        {
            _ps = new PropertySet();
            _ps.MapChanged += this.MapChangedHandler;
        }

        public PropertySet PropertySet { get { return _ps; } }

        int[] counts = { 0, 0, 0, 0 };
        private void MapChangedHandler(IObservableMap<string, object> sender,
            IMapChangedEventArgs<string> args)
        {
            counts[(int)args.CollectionChange] += 1;
        }

        public string DisplayStats()
        {
            StringBuilder report = new StringBuilder("<br/>Number of changes:<ul>");
            for (int i = 0; i < counts.Length; i++)
            {
                report.Append("<li>" + (CollectionChange)i + ": " + counts[i] + "</li>");
            }
            return report.ToString() + "</ul>";
        }
    }
}
Imports System.Text

Public NotInheritable Class PropertySetStats
    Private _ps As PropertySet
    Public Sub New()
        _ps = New PropertySet()
        AddHandler _ps.MapChanged, AddressOf Me.MapChangedHandler
    End Sub

    Public ReadOnly Property PropertySet As PropertySet
        Get
            Return _ps
        End Get
    End Property

    Dim counts() As Integer = {0, 0, 0, 0}
    Private Sub MapChangedHandler(ByVal sender As IObservableMap(Of String, Object),
        ByVal args As IMapChangedEventArgs(Of String))

        counts(CInt(args.CollectionChange)) += 1
    End Sub

    Public Function DisplayStats() As String
        Dim report As New StringBuilder("<br/>Number of changes:<ul>")
        For i As Integer = 0 To counts.Length - 1
            report.Append("<li>" & CType(i, CollectionChange).ToString() &
                          ": " & counts(i) & "</li>")
        Next
        Return report.ToString() & "</ul>"
    End Function
End Class

イベントハンドラーは、使い慣れた .NET Framework イベントパターンに従います。ただし、イベントの送信者 (この場合は PropertySet オブジェクト) が IObservableMap <string、object > インターフェイス (Visual の IObservableMap (Of String, Object)) にキャストされる点が異なります。Basic)。 Windows ランタイムインターフェイスIObservableMap <K V >のインスタンス化です。The event handler follows the familiar .NET Framework event pattern, except that the sender of the event (in this case, the PropertySet object) is cast to the IObservableMap<string, object> interface (IObservableMap(Of String, Object) in Visual Basic), which is an instantiation of the Windows Runtime interface IObservableMap<K, V>. (必要に応じて、送信元をその型にキャストできます)。また、イベント引数は、オブジェクトとしてではなくインターフェイスとして示されます。(You can cast the sender to its type if necessary.) Also, the event arguments are presented as an interface rather than as an object.

default.js ファイルで、次のように runtime1 関数を追加します。In the default.js file, add the Runtime1 function as shown. このコードでは、PropertySetStats オブジェクトを作成し、PropertySet コレクションを取得します。また、独自のイベント ハンドラーである onMapChanged 関数を追加して、MapChanged イベントを処理します。This code creates a PropertySetStats object, gets its PropertySet collection, and adds its own event handler, the onMapChanged function, to handle the MapChanged event. コレクションの変更後、runtime1 は DisplayStats メソッドを呼び出して、変更の種類の概要を表示します。After making changes to the collection, runtime1 calls the DisplayStats method to show a summary of change types.

var propertysetstats;

function runtime1() {
    document.getElementById('output').innerHTML = "";

    propertysetstats = new SampleComponent.PropertySetStats();
    var propertyset = propertysetstats.propertySet;

    propertyset.addEventListener("mapchanged", onMapChanged);

    propertyset.insert("FirstProperty", "First property value");
    propertyset.insert("SuperfluousProperty", "Unnecessary property value");
    propertyset.insert("AnotherProperty", "A property value");

    propertyset.insert("SuperfluousProperty", "Altered property value")
    propertyset.remove("SuperfluousProperty");

    document.getElementById('output').innerHTML +=
        propertysetstats.displayStats();
}

function onMapChanged(change) {
    var result
    switch (change.collectionChange) {
        case Windows.Foundation.Collections.CollectionChange.reset:
            result = "All properties cleared";
            break;
        case Windows.Foundation.Collections.CollectionChange.itemInserted:
            result = "Inserted " + change.key + ": '" +
                change.target.lookup(change.key) + "'";
            break;
        case Windows.Foundation.Collections.CollectionChange.itemRemoved:
            result = "Removed " + change.key;
            break;
        case Windows.Foundation.Collections.CollectionChange.itemChanged:
            result = "Changed " + change.key + " to '" +
                change.target.lookup(change.key) + "'";
            break;
        default:
            break;
     }

     document.getElementById('output').innerHTML +=
         "<br/>" + result;
}

JavaScript で Windows ランタイム イベントを処理する方法は、.NET Framework コードで処理する方法とは大きく異なります。The way you handle Windows Runtime events in JavaScript is very different from the way you handle them in .NET Framework code. JavaScript イベント ハンドラーは引数を 1 つだけ受け取ります。The JavaScript event handler takes only one argument. Visual Studio デバッガーでこのオブジェクトを表示した場合、最初のプロパティが送信元です。When you view this object in the Visual Studio debugger, the first property is the sender. イベント引数インターフェイスのメンバーも、このオブジェクトに直接表示されます。The members of the event argument interface also appear directly on this object.

アプリを実行するには、F5 キーを押します。To run the app, choose the F5 key. クラスがシールされていない場合、"Exporting unsealed type 'SampleComponent.Example' is not currently supported.If the class is not sealed, you get the error message, "Exporting unsealed type 'SampleComponent.Example' is not currently supported. Please mark it as sealed." (unsealed 型 'SampleComponent.Example' のエクスポートは現在サポートされていません。sealed としてマークしてください。) というエラー メッセージが表示されます。Please mark it as sealed."

[Runtime 1] ボタンをクリックします。Choose the Runtime 1 button. 要素が追加または変更されると、イベント ハンドラーが変更を表示し、最後に DisplayStats メソッドが呼び出されて変更の数の概要が生成されます。The event handler displays changes as elements are added or changed, and at the end the DisplayStats method is called to produce a summary of counts. デバッグを停止してアプリを閉じるには、Visual Studio に戻り、Shift キーを押しながら F5 キーを押します。To stop debugging and close the app, switch back to Visual Studio and choose Shift+F5.

マネージ コードから PropertySet コレクションにさらに 2 つの項目を追加するには、次のコードを PropertySetStats クラスに追加します。To add two more items to the PropertySet collection from managed code, add the following code to the PropertySetStats class:

public void AddMore()
{
    _ps.Add("NewProperty", "New property value");
    _ps.Add("AnotherProperty", "A property value");
}
Public Sub AddMore()
    _ps.Add("NewProperty", "New property value")
    _ps.Add("AnotherProperty", "A property value")
End Sub

このコードは、2 つの環境での Windows ランタイム型の使用方法のもう 1 つの違いを示しています。This code highlights another difference in the way you use Windows Runtime types in the two environments. このコードを自分で入力すると、IntelliSense が JavaScript コードで使用した insert メソッドを表示しないことがわかります。If you type this code yourself, you'll notice that IntelliSense doesn't show the insert method you used in the JavaScript code. 代わりに、.NET のコレクションでよく見られる Add メソッドを示しています。Instead, it shows the Add method commonly seen on collections in .NET. これは、一般的に使用されるコレクションインターフェイスの名前は異なりますが、Windows ランタイムと .NET でも同様の機能を持つためです。This is because some commonly used collection interfaces have different names but similar functionality in the Windows Runtime and .NET. マネージ コードでこれらのインターフェイスを使用すると、.NET Framework の対応するインターフェイスとして表示されます。When you use these interfaces in managed code, they appear as their .NET Framework equivalents. これについては、「 C# 」および「Visual Basic の Windows ランタイムコンポーネント」で説明されています。This is discussed in Windows Runtime components with C# and Visual Basic. JavaScript で同じインターフェイスを使用した場合、Windows ランタイムからの変更点は、メンバー名の先頭の大文字が小文字になることだけです。When you use the same interfaces in JavaScript, the only change from the Windows Runtime is that uppercase letters at the beginning of member names become lowercase.

最後に、例外処理で AddMore メソッドを呼び出すには、runtime2 関数を default.js に追加します。Finally, to call the AddMore method with exception handling, add the runtime2 function to default.js.

function runtime2() {
   try {
      propertysetstats.addMore();
    }
   catch(ex) {
       document.getElementById('output').innerHTML +=
          "<br/><b>" + ex + "<br/>";
   }

   document.getElementById('output').innerHTML +=
       propertysetstats.displayStats();
}

前と同様に、イベント ハンドラーの登録コードを追加します。Add the event handler registration code the same way you did previously.

var runtimeButton1 = document.getElementById("runtimeButton1");
runtimeButton1.addEventListener("click", runtime1, false);
var runtimeButton2 = document.getElementById("runtimeButton2");
runtimeButton2.addEventListener("click", runtime2, false);

アプリを実行するには、F5 キーを押します。To run the app, choose the F5 key. [Runtime 1][Runtime 2] の順にクリックします。Choose Runtime 1 and then Runtime 2. JavaScript イベント ハンドラーはコレクションの最初の変更を報告します。The JavaScript event handler reports the first change to the collection. ただし、2 番目の変更には重複するキーがあります。The second change, however, has a duplicate key. .NET Framework ディクショナリのユーザーは、Add メソッドが例外をスローすることを想定しており、実際にそのとおりになります。Users of .NET Framework dictionaries expect the Add method to throw an exception, and that is what happens. JavaScript は .NET 例外を処理します。JavaScript handles the .NET exception.

  You JavaScript コードから例外のメッセージを表示することはできません。Note  You can't display the exception's message from JavaScript code. メッセージ テキストはスタック トレースに置き換えられます。The message text is replaced by a stack trace. 詳細については、「」および「Visual Basic でのC# Windows ランタイムコンポーネントの作成」の「例外のスロー」を参照してください。For more information, see "Throwing exceptions" in Creating Windows Runtime components in C# and Visual Basic.

一方、JavaScript が重複するキーで insert メソッドを呼び出したときには、項目の値が変更されました。By contrast, when JavaScript called the insert method with a duplicate key, the value of the item was changed. この動作の違いは、「」および「Visual Basic でC#のコンポーネントの Windows ランタイム」で説明されているように、JavaScript と .net が Windows ランタイムをサポートするさまざまな方法です。This difference in behavior is due to the different ways that JavaScript and .NET support the Windows Runtime, as explained in Windows Runtime components with C# and Visual Basic.

コンポーネントからマネージ型を返すReturning managed types from your component

前述のように、JavaScript コードと C# または Visual Basic のコード間で、ネイティブの Windows ランタイム型を自由に受け渡すことができます。As discussed previously, you can pass native Windows Runtime types back and forth freely between your JavaScript code and your C# or Visual Basic code. ほとんどの場合、型名とメンバー名はどちらの場合も同じになります (JavaScript ではメンバー名が小文字で始まる点を除きます)。Most of the time, the type names and member names will be the same in both cases (except that the member names start with lowercase letters in JavaScript). ただし、前のセクションでは、マネージ コードで PropertySet クラスのメンバーが異なっていましたHowever, in the preceding section, the PropertySet class appeared to have different members in managed code. (たとえば、JavaScript では insert メソッドを呼び出しましたが、.NET コードでは Add メソッドを呼び出しました)。このセクションでは、これらの違いが JavaScript に渡される .NET Framework 型にどのように影響するかについて説明します。(For example, in JavaScript you called the insert method, and in the .NET code you called the Add method.) This section explores the way those differences affect .NET Framework types passed to JavaScript.

コンポーネントで作成した Windows ランタイム型または JavaScript からコンポーネントに渡された Windows ランタイム型を返すだけでなく、マネージ コードで作成されたマネージ型を、対応する Windows ランタイム型と同様に JavaScript に返すこともできます。In addition to returning Windows Runtime types that you created in your component or passed to your component from JavaScript, you can return a managed type, created in managed code, to JavaScript as if it were the corresponding Windows Runtime type. ランタイム クラスの最初の簡単な例でも、メンバーのパラメーターと戻り値の型は、Visual Basic または C# のプリミティブ型 (.NET Framework の型) でした。Even in the first, simple example of a runtime class, the parameters and return types of the members were Visual Basic or C# primitive types, which are .NET Framework types. コレクションでこれを示すために、Example クラスに次のコードを追加して、整数でインデックス付けされた文字列のジェネリック ディクショナリを返すメソッドを作成します。To demonstrate this for collections, add the following code to the Example class, to create a method that returns a generic dictionary of strings, indexed by integers:

public static IDictionary<int, string> GetMapOfNames()
{
    Dictionary<int, string> retval = new Dictionary<int, string>();
    retval.Add(1, "one");
    retval.Add(2, "two");
    retval.Add(3, "three");
    retval.Add(42, "forty-two");
    retval.Add(100, "one hundred");
    return retval;
}
Public Shared Function GetMapOfNames() As IDictionary(Of Integer, String)
    Dim retval As New Dictionary(Of Integer, String)
    retval.Add(1, "one")
    retval.Add(2, "two")
    retval.Add(3, "three")
    retval.Add(42, "forty-two")
    retval.Add(100, "one hundred")
    Return retval
End Function

ディクショナリは、Dictionary<TKey, TValue> によって実装され、Windows ランタイム インターフェイスにマップされるインターフェイスとして返される必要があることに注意してください。Notice that the dictionary must be returned as an interface that is implemented by Dictionary<TKey, TValue>, and that maps to a Windows Runtime interface. この例では、インターフェイスは IDictionary<int, string> (Visual Basic では IDictionary(Of Integer, String)) です。In this case, the interface is IDictionary<int, string> (IDictionary(Of Integer, String) in Visual Basic). Windows ランタイム型の IMap<int, string> がマネージ コードに渡されると、IDictionary<int, string> として表示され、マネージ型が JavaScript に渡されると、この逆になります。When the Windows Runtime type IMap<int, string> is passed to managed code, it appears as IDictionary<int, string>, and the reverse is true when the managed type is passed to JavaScript.

重要  When マネージ型が複数のインターフェイスを実装する場合、JavaScript はリストの先頭に表示されるインターフェイスを使用します。Important  When a managed type implements multiple interfaces, JavaScript uses the interface that appears first in the list. たとえば、Dictionary<int, string> を JavaScript コードに返した場合、戻り値の型としてどのインターフェイスを指定しても、IDictionary<int, string> として表示されます。For example, if you return Dictionary<int, string> to JavaScript code, it appears as IDictionary<int, string> no matter which interface you specify as the return type. これは、後のインターフェイスで表示されるメンバーが最初のインターフェイスに含まれていない場合、そのメンバーは JavaScript に認識されないことを意味します。This means that if the first interface doesn't include a member that appears on later interfaces, that member isn't visible to JavaScript.

 

新しいメソッドをテストしてディクショナリを使用するには、returns1 関数と returns2 関数を default.js に追加します。To test the new method and use the dictionary, add the returns1 and returns2 functions to default.js:

var names;

function returns1() {
    names = SampleComponent.Example.getMapOfNames();
    document.getElementById('output').innerHTML = showMap(names);
}

var ct = 7;

function returns2() {
    if (!names.hasKey(17)) {
        names.insert(43, "forty-three");
        names.insert(17, "seventeen");
    }
    else {
        var err = names.insert("7", ct++);
        names.insert("forty", "forty");
    }
    document.getElementById('output').innerHTML = showMap(names);
}

function showMap(map) {
    var item = map.first();
    var retval = "<ul>";

    for (var i = 0, len = map.size; i < len; i++) {
        retval += "<li>" + item.current.key + ": " + item.current.value + "</li>";
        item.moveNext();
    }
    return retval + "</ul>";
}

イベント登録コードを、他のイベント登録コードと同じ then ブロックに追加します。Add the event registration code to the same then block as the other event registration code:

var returnsButton1 = document.getElementById("returnsButton1");
returnsButton1.addEventListener("click", returns1, false);
var returnsButton2 = document.getElementById("returnsButton2");
returnsButton2.addEventListener("click", returns2, false);

この JavaScript コードには、注目すべき点がいくつかあります。There are a few interesting things to observe about this JavaScript code. まず、ディクショナリの内容を HTML で表示する showMap 関数が含まれています。First of all, it includes a showMap function to display the contents of the dictionary in HTML. showMap のコードのイテレーション パターンに注目してください。In the code for showMap, notice the iteration pattern. .NET では、汎用 IDictionary インターフェイスに最初のメソッドがなく、サイズがサイズのメソッドではなく Count プロパティによって返されます。In .NET, there's no First method on the generic IDictionary interface, and the size is returned by a Count property rather than by a Size method. JavaScript に対して、IDictionary<int, string> は Windows ランタイム型の IMap<int, string> として表示されますTo JavaScript, IDictionary<int, string> appears to be the Windows Runtime type IMap<int, string>. (IMap<K,V> インターフェイスをご覧ください)。(See the IMap<K,V> interface.)

前の例のように、returns2 関数では、JavaScript が Insert メソッド (JavaScript では insert) を呼び出して項目をディクショナリに追加します。In the returns2 function, as in earlier examples, JavaScript calls the Insert method (insert in JavaScript) to add items to the dictionary.

アプリを実行するには、F5 キーを押します。To run the app, choose the F5 key. ディクショナリの初期内容を作成して表示するには、 [Returns 1] ボタンをクリックします。To create and display the initial contents of the dictionary, choose the Returns 1 button. ディクショナリにさらに 2 つのエントリを追加するには、 [Returns 2] ボタンをクリックします。To add two more entries to the dictionary, choose the Returns 2 button. Dictionary<TKey, TValue> から想定されるように、エントリは挿入順に表示されます。Notice that the entries are displayed in order of insertion, as you would expect from Dictionary<TKey, TValue>. エントリを並べ替える場合は、GetMapOfNames から SortedDictionary<int, string> を返すことができますIf you want them sorted, you can return a SortedDictionary<int, string> from GetMapOfNames. (前の例で使われている PropertySet クラスの内部構成は、Dictionary<TKey, TValue> とは異なります)。(The PropertySet class used in earlier examples has a different internal organization from Dictionary<TKey, TValue>.)

JavaScript は厳密に型指定された言語ではないため、厳密に型指定されたジェネリック コレクションを使うと、予期しない結果になる場合があります。Of course, JavaScript is not a strongly typed language, so using strongly typed generic collections can lead to some surprising results. [Returns 2] ボタンをもう一度クリックします。Choose the Returns 2 button again. JavaScript は "7" を数値 7 に強制的に変換し、ct に格納された数値 7 を文字列に変換します。JavaScript obligingly coerces the "7" to a numeric 7, and the numeric 7 that's stored in ct to a string. さらに、この文字列 "forty" を強制的にゼロに変換します。And it coerces the string "forty" to zero. しかし、これは始まりにすぎません。But that's only the beginning. [Returns 2] ボタンをさらに数回クリックします。Choose the Returns 2 button a few more times. マネージ コードでは、値が正しい型にキャストされていても、Add メソッドは重複キーの例外を生成します。In managed code, the Add method would generate duplicate key exceptions, even if the values were cast to the correct types. これに対して、Insert メソッドは既存のキーに関連付けられている値を更新し、新しいキーがディクショナリに追加されたかどうかを示すブール値を返します。In contrast, the Insert method updates the value associated with an existing key and returns a Boolean value that indicates whether a new key was added to the dictionary. キー 7 に関連付けられている値が変わり続けるのはこのためです。This is why the value associated with the key 7 keeps changing.

予期しない動作がもう 1 つあります。未割り当ての JavaScript 変数を文字列引数として渡すと、"undefined" という文字列が返されます。Another unexpected behavior: If you pass an unassigned JavaScript variable as a string argument, what you get is the string "undefined". つまり、.NET Framework のコレクション型を JavaScript コードに渡すときには注意が必要です。In short, be careful when you pass .NET Framework collection types to your JavaScript code.

連結する大量のテキストがある   If、 showmap 関数に示されているように、コードを .NET Framework メソッドに移動し、StringBuilder クラスを使用すると、より効率的に実行できます。Note  If you have large quantities of text to concatenate, you can do it more efficiently by moving the code into a .NET Framework method and using the StringBuilder class, as shown in the showMap function.

Windows ランタイム コンポーネントから独自のジェネリック型を公開することはできませんが、次のようなコードを使って Windows ランタイム クラスの .NET Framework ジェネリック コレクションを返すことができます。Although you can't expose your own generic types from a Windows Runtime component, you can return .NET Framework generic collections for Windows Runtime classes by using code such as the following:

public static object GetListOfThis(object obj)
{
    Type target = obj.GetType();
    return Activator.CreateInstance(typeof(List<>).MakeGenericType(target));
}
Public Shared Function GetListOfThis(obj As Object) As Object
    Dim target As Type = obj.GetType()
    Return Activator.CreateInstance(GetType(List(Of )).MakeGenericType(target))
End Function

List<T> は IList<T> を実装しており、JavaScript では Windows ランタイム型の IVector<T> として表示されます。List<T> implements IList<T>, which appears as the Windows Runtime type IVector<T> in JavaScript.

イベントの宣言Declaring events

イベントを宣言するには、.NET Framework の標準のイベント パターン、または Windows ランタイムで使用される他のパターンを使うことができます。You can declare events by using the standard .NET Framework event pattern or other patterns used by the Windows Runtime. .NET Framework は、System.EventHandler<TEventArgs> デリゲートと Windows ランタイムの EventHandler<T> デリゲート間の等価性をサポートするので、.NET Framework の標準パターンを実装するときは、EventHandler<TEventArgs> を使うと便利です。The .NET Framework supports equivalence between the System.EventHandler<TEventArgs> delegate and the Windows Runtime EventHandler<T> delegate, so using EventHandler<TEventArgs> is a good way to implement the standard .NET Framework pattern. この動作を確認するために、SampleComponent プロジェクトにクラスの次の組み合わせを追加します。To see how this works, add the following pair of classes to the SampleComponent project:

namespace SampleComponent
{
    public sealed class Eventful
    {
        public event EventHandler<TestEventArgs> Test;
        public void OnTest(string msg, long number)
        {
            EventHandler<TestEventArgs> temp = Test;
            if (temp != null)
            {
                temp(this, new TestEventArgs()
                {
                    Value1 = msg,
                    Value2 = number
                });
            }
        }
    }

    public sealed class TestEventArgs
    {
        public string Value1 { get; set; }
        public long Value2 { get; set; }
    }
}
Public NotInheritable Class Eventful
    Public Event Test As EventHandler(Of TestEventArgs)
    Public Sub OnTest(ByVal msg As String, ByVal number As Long)
        RaiseEvent Test(Me, New TestEventArgs() With {
                            .Value1 = msg,
                            .Value2 = number
                            })
    End Sub
End Class

Public NotInheritable Class TestEventArgs
    Public Property Value1 As String
    Public Property Value2 As Long
End Class

Windows ランタイムでイベントを公開すると、イベント引数クラスは System.Object から継承します。When you expose an event in the Windows Runtime, the event argument class inherits from System.Object. EventArgs は Windows ランタイム型ではないため、.NET の場合と同様に、system.object から継承することはありません。It doesn't inherit from System.EventArgs, as it would in .NET, because EventArgs is not a Windows Runtime type.

イベントのカスタム イベント アクセサー (Visual Basic では Custom キーワード) を宣言する場合は、Windows ランタイムのイベント パターンを使用する必要があります。If you declare custom event accessors for your event (Custom keyword in Visual Basic), you must use the Windows Runtime event pattern. Windows ランタイムコンポーネント」の「カスタムイベントとイベントアクセサー」を参照してください。See Custom events and event accessors in Windows Runtime components.

Test イベントを処理するには、events1 関数を default.js に追加します。To handle the Test event, add the events1 function to default.js. events1 関数は Test イベントのイベント ハンドラー関数を作成し、OnTest メソッドを即座に呼び出してイベントを発生させます。The events1 function creates an event handler function for the Test event, and immediately invokes the OnTest method to raise the event. イベント ハンドラーの本体にブレークポイントを配置すると、単一のパラメーターに渡されるオブジェクトにソース オブジェクトと TestEventArgs の両方のメンバーが含まれていることを確認できます。If you place a breakpoint in the body of the event handler, you can see that the object passed to the single parameter includes the source object and both members of TestEventArgs.

var ev;

function events1() {
   ev = new SampleComponent.Eventful();
   ev.addEventListener("test", function (e) {
       document.getElementById('output').innerHTML = e.value1;
       document.getElementById('output').innerHTML += "<br/>" + e.value2;
   });
   ev.onTest("Number of feet in a mile:", 5280);
}

イベント登録コードを、他のイベント登録コードと同じ then ブロックに追加します。Add the event registration code to the same then block as the other event registration code:

var events1Button = document.getElementById("events1Button");
events1Button.addEventListener("click", events1, false);

非同期操作の公開Exposing asynchronous operations

.NET Framework には、Task クラスとジェネリック Task<TResult> クラスに基づく、非同期処理と並列処理のための豊富なツール セットがあります。The .NET Framework has a rich set of tools for asynchronous processing and parallel processing, based on the Task and generic Task<TResult> classes. Windows ランタイム コンポーネントでタスク ベースの非同期処理を公開するには、IAsyncActionIAsyncActionWithProgress<TProgress>IAsyncOperation<TResult>IAsyncOperationWithProgress<TResult, TProgress> の各 Windows ランタイム インターフェイスを使いますTo expose task-based asynchronous processing in a Windows Runtime component, use the Windows Runtime interfaces IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, and IAsyncOperationWithProgress<TResult, TProgress>. (Windows ランタイムでは、操作は結果を返しますが、アクションは結果を返しません)。(In the Windows Runtime, operations return results, but actions do not.)

このセクションでは、進行状況を報告し、結果を返す取り消し可能な非同期操作を示します。This section demonstrates a cancelable asynchronous operation that reports progress and returns results. GetPrimesInRangeAsync メソッドは、AsyncInfo クラスを使用してタスクを生成し、取り消し機能と進行状況レポート機能を WinJS.Promise オブジェクトに関連付けます。The GetPrimesInRangeAsync method uses the AsyncInfo class to generate a task and to connect its cancellation and progress-reporting features to a WinJS.Promise object. まず、GetPrimesInRangeAsync メソッドをサンプル クラスに追加します。Begin by adding the GetPrimesInRangeAsync method to the example class:

using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;

public static IAsyncOperationWithProgress<IList<long>, double>
GetPrimesInRangeAsync(long start, long count)
{
    if (start < 2 || count < 1) throw new ArgumentException();

    return AsyncInfo.Run<IList<long>, double>((token, progress) =>

        Task.Run<IList<long>>(() =>
        {
            List<long> primes = new List<long>();
            double onePercent = count / 100;
            long ctProgress = 0;
            double nextProgress = onePercent;

            for (long candidate = start; candidate < start + count; candidate++)
            {
                ctProgress += 1;
                if (ctProgress >= nextProgress)
                {
                    progress.Report(ctProgress / onePercent);
                    nextProgress += onePercent;
                }
                bool isPrime = true;
                for (long i = 2, limit = (long)Math.Sqrt(candidate); i <= limit; i++)
                {
                    if (candidate % i == 0)
                    {
                        isPrime = false;
                        break;
                    }
                }
                if (isPrime) primes.Add(candidate);

                token.ThrowIfCancellationRequested();
            }
            progress.Report(100.0);
            return primes;
        }, token)
    );
}
Imports System.Runtime.InteropServices.WindowsRuntime

Public Shared Function GetPrimesInRangeAsync(ByVal start As Long, ByVal count As Long)
As IAsyncOperationWithProgress(Of IList(Of Long), Double)

    If (start < 2 Or count < 1) Then Throw New ArgumentException()

    Return AsyncInfo.Run(Of IList(Of Long), Double)( _
        Function(token, prog)
            Return Task.Run(Of IList(Of Long))( _
                Function()
                    Dim primes As New List(Of Long)
                    Dim onePercent As Long = count / 100
                    Dim ctProgress As Long = 0
                    Dim nextProgress As Long = onePercent

                    For candidate As Long = start To start + count - 1
                        ctProgress += 1

                        If ctProgress >= nextProgress Then
                            prog.Report(ctProgress / onePercent)
                            nextProgress += onePercent
                        End If

                        Dim isPrime As Boolean = True
                        For i As Long = 2 To CLng(Math.Sqrt(candidate))
                            If (candidate Mod i) = 0 Then
                                isPrime = False
                                Exit For
                            End If
                        Next

                        If isPrime Then primes.Add(candidate)

                        token.ThrowIfCancellationRequested()
                    Next
                    prog.Report(100.0)
                    Return primes
                End Function, token)
        End Function)
End Function

GetPrimesInRangeAsync は非常にシンプルな素数ファインダーであり、これは仕様です。GetPrimesInRangeAsync is a very simple prime number finder, and that's by design. ここでは非同期操作の実装に重点を置いているので、シンプルであることが重要であり、キャンセルを示すときに低速の実装が利点となります。The focus here is on implementing an asynchronous operation, so simplicity is important, and a slow implementation is an advantage when we're demonstrating cancellation. GetPrimesInRangeAsync はブルート フォース方式で素数を見つけます。つまり、素数だけを使うのではなく、候補をその平方根以下のすべての整数で除算します。GetPrimesInRangeAsync finds primes by brute force: It divides a candidate by all the integers that are less than or equal to its square root, rather than using only the prime numbers. このコードのステップ実行は次のとおりです。Stepping through this code:

  • 非同期操作を開始する前に、パラメーターの検証や無効な入力に対する例外のスローなどのハウスキーピング アクティビティを実行します。Before starting an asynchronous operation, perform housekeeping activities such as validating parameters and throwing exceptions for invalid input.

  • この実装で重要になるのは、AsyncInfo.Run<TResult, TProgress>(Func<CancellationToken, IProgress<TProgress>, Task<TResult>>) メソッドと、このメソッドの唯一のパラメーターであるデリゲートです。The key to this implementation is the AsyncInfo.Run<TResult, TProgress>(Func<CancellationToken, IProgress<TProgress>, Task<TResult>>) method, and the delegate that is the method's only parameter. デリゲートはキャンセル トークンと進行状況を報告するためのインターフェイスを受け取り、それらのパラメーターを使う開始タスクを返す必要があります。The delegate must accept a cancellation token and an interface for reporting progress, and must return a started task that uses those parameters. JavaScript が GetPrimesInRangeAsync メソッドを呼び出すと、次の手順が発生します (ここで示す順序とは限りません)。When JavaScript calls the GetPrimesInRangeAsync method, the following steps occur (not necessarily in the order given here):

    • WinJS.Promise オブジェクトは、返された結果の処理、キャンセルへの対応、進行状況レポートの処理を行う関数を提供します。The WinJS.Promise object supplies functions to process the returned results, react to cancellation, and handle progress reports.

    • AsyncInfo.Run メソッドは、キャンセル ソースと、IProgress<T> インターフェイスを実装するオブジェクトを作成します。The AsyncInfo.Run method creates a cancellation source and an object that implements the IProgress<T> interface. デリゲートに対して、キャンセル ソースからの CancellationToken トークンと、IProgress<T> インターフェイスの両方を渡します。To the delegate, it passes both a CancellationToken token from the cancellation source, and the IProgress<T> interface.

      Promise オブジェクトがキャンセル、AsyncInfo に応答する関数を提供していない   If、 実行後もキャンセル可能なトークンを渡し、キャンセルが発生する可能性があります。Note  If the Promise object doesn't supply a function to react to cancellation, AsyncInfo.Run still passes a cancelable token, and cancellation can still occur. Promise オブジェクトが進行状況の更新を処理する関数を提供しない場合、AsyncInfo.Run は IProgress<T> を実装するオブジェクトを引き続き提供しますが、レポートは無視されます。If the Promise object doesn't supply a function to handle progress updates, AsyncInfo.Run still supplies an object that implements IProgress<T>, but its reports are ignored.

    • デリゲートは Task.Run<TResult>(Func<TResult>, CancellationToken) メソッドを使って、トークンと進行状況インターフェイスを使う開始タスクを作成します。The delegate uses the Task.Run<TResult>(Func<TResult>, CancellationToken) method to create a started task that uses the token and the progress interface. 開始タスクのデリゲートは、目的の結果を計算するラムダ関数によって提供されます。The delegate for the started task is provided by a lambda function that computes the desired result. この詳細については後述します。More about that in a moment.

    • AsyncInfo.Run メソッドは、IAsyncOperationWithProgress<TResult, TProgress> インターフェイスを実装するオブジェクトを作成し、Windows ランタイムのキャンセル メカニズムをトークン ソースに関連付け、Promise オブジェクトの進行状況レポート関数を IProgress<T> インターフェイスに関連付けます。The AsyncInfo.Run method creates an object that implements the IAsyncOperationWithProgress<TResult, TProgress> interface, connects the Windows Runtime cancellation mechanism with the token source, and connects the Promise object's progress-reporting function with the IProgress<T> interface.

    • IAsyncOperationWithProgress<TResult, TProgress> インターフェイスが JavaScript に返されます。The IAsyncOperationWithProgress<TResult, TProgress> interface is returned to JavaScript.

  • 開始タスクで表されるラムダ関数は引数を受け取りません。The lambda function that is represented by the started task doesn't take any arguments. ラムダ関数であるため、トークンと IProgress インターフェイスにアクセスできます。Because it's a lambda function, it has access to the token and the IProgress interface. 候補の数値が評価されるたびに、ラムダ関数は以下を実行します。Each time a candidate number is evaluated, the lambda function:

    • 進行状況の次のパーセント ポイントに到達したかどうかを確認します。Checks to see whether the next percentage point of progress has been reached. 到達した場合、ラムダ関数は IProgress<T>.Report メソッドを呼び出し、Promise オブジェクトが進行状況を報告するために指定した関数にパーセンテージが渡されます。If it has, the lambda function calls the IProgress<T>.Report method, and the percentage is passed through to the function that the Promise object specified for reporting progress.
    • 操作が取り消された場合は、キャンセル トークンを使って例外をスローします。Uses the cancellation token to throw an exception if the operation has been canceled. IAsyncInfo.Cancel メソッド (IAsyncOperationWithProgress<TResult, TProgress> インターフェイスが継承するメソッド) が呼び出された場合、AsyncInfo.Run メソッドが設定した関連付けにより、キャンセル トークンに確実に通知されます。If the IAsyncInfo.Cancel method (which the IAsyncOperationWithProgress<TResult, TProgress> interface inherits) has been called, the connection that the AsyncInfo.Run method set up ensures that the cancellation token is notified.
  • ラムダ関数が素数のリストを返すと、WinJS.Promise オブジェクトが結果を処理するために指定した関数にこのリストが渡されます。When the lambda function returns the list of prime numbers, the list is passed to the function that the WinJS.Promise object specified for processing the results.

JavaScript Promise を作成し、キャンセル メカニズムを設定するには、asyncRun 関数と asyncCancel 関数を default.js に追加します。To create the JavaScript promise and set up the cancellation mechanism, add the asyncRun and asyncCancel functions to default.js.

var resultAsync;
function asyncRun() {
    document.getElementById('output').innerHTML = "Retrieving prime numbers.";
    btnAsync.disabled = "disabled";
    btnCancel.disabled = "";

    resultAsync = SampleComponent.Example.getPrimesInRangeAsync(10000000000001, 2500).then(
        function (primes) {
            for (i = 0; i < primes.length; i++)
                document.getElementById('output').innerHTML += " " + primes[i];

            btnCancel.disabled = "disabled";
            btnAsync.disabled = "";
        },
        function () {
            document.getElementById('output').innerHTML += " -- getPrimesInRangeAsync was canceled. -- ";

            btnCancel.disabled = "disabled";
            btnAsync.disabled = "";
        },
        function (prog) {
            document.getElementById('primeProg').value = prog;
        }
    );
}

function asyncCancel() {    
    resultAsync.cancel();
}

これまでと同様に、イベント登録コードを忘れないでください。Don't forget the event registration code the same as you did previously.

var btnAsync = document.getElementById("btnAsync");
btnAsync.addEventListener("click", asyncRun, false);
var btnCancel = document.getElementById("btnCancel");
btnCancel.addEventListener("click", asyncCancel, false);

非同期の GetPrimesInRangeAsync メソッドを呼び出すことで、asyncRun 関数は WinJS.Promise オブジェクトを作成します。By calling the asynchronous GetPrimesInRangeAsync method, the asyncRun function creates a WinJS.Promise object. このオブジェクトの then メソッドは、返される結果の処理、エラーへの対応 (キャンセルを含む)、進行状況レポートの処理を行う 3 つの関数を受け取ります。The object's then method takes three functions that process the returned results, react to errors (including cancellation), and handle progress reports. この例では、返された結果が出力領域に表示されます。In this example, the returned results are printed in the output area. キャンセルまたは完了により、操作を開始するボタンと操作を取り消すボタンがリセットされます。Cancellation or completion resets the buttons that launch and cancel the operation. 進行状況レポートにより、プログレス コントロールが更新されます。Progress reporting updates the progress control.

asyncCancel 関数は、WinJS.Promise オブジェクトの cancel メソッドを呼び出すだけです。The asyncCancel function just calls the cancel method of the WinJS.Promise object.

アプリを実行するには、F5 キーを押します。To run the app, choose the F5 key. 非同期操作を開始するには、 [Async] ボタンをクリックします。To start the asynchronous operation, choose the Async button. 次に行われる処理は、コンピューターの速度によって異なります。What happens next depends on how fast your computer is. 点滅時間になる前に進行状況バーが完了まで進む場合は、10 個の中の 1 つ以上の要素によって GetPrimesInRangeAsync に渡される開始番号を大きくします。If the progress bar zips to completion before you have time to blink, increase the size of the starting number that is passed to GetPrimesInRangeAsync by one or more factors of ten. テストする数値の数の増減によって操作の時間を調整できますが、開始番号の途中にゼロを追加すると影響が大きくなります。You can fine-tune the duration of the operation by increasing or decreasing the count of numbers to test, but adding zeros in the middle of the starting number will have a bigger impact. 操作を取り消すには、 [Cancel Async] ボタンを選びます。To cancel the operation, choose the Cancel Async button.