Udostępnij za pośrednictwem


Tworzenie operacji asynchronicznych w języku C++ dla aplikacji sklepu Windows Store

W tym dokumencie opisano niektóre z najważniejszych punktów, o których warto pamiętać, gdy używasz Runtime współbieżności do produkcji operacji asynchronicznych w Windows Store aplikacji.

Korzystanie z asynchronicznego programowania jest kluczowym elementem w Windows Store model aplikacji, ponieważ umożliwia to aplikacje zapewniać możliwość reagowania na działania użytkownika.Długo wykonujące zadania mogą być uruchamiane bez blokowania wątku interfejsu użytkownika, a otrzymasz wyniki zadania później.Można także anulować zadania i otrzymywać powiadomienia o postępie jako zadania w tle.Dokument asynchroniczno Programowanie w języku C++ zawiera omówienie asynchronicznego wzór, który jest dostępny w programie Visual C++ do tworzenia Windows Store aplikacji.Ten dokument uczy jak zarówno zużywają i tworzenie łańcuchów asynchroniczne Środowisko wykonawcze systemu Windows operacji.W tej sekcji informacje dotyczące używania środowiska wykonawczego współbieżności do produkcji operacji asynchronicznych, które mogą być wykorzystane przez innego Środowisko wykonawcze systemu Windows składnik i jak kontrolować sposób asynchroniczny praca jest wykonywana.Również pod uwagę poczytać asynchronicznego programowania desenie i porad zawartych w Hilo (apps magazynu systemu Windows przy użyciu języka C++ lub XAML) Aby dowiedzieć się jak kiedyś Runtime współbieżności do realizacji operacji asynchronicznych w Hilo, Windows Store aplikacji za pomocą języków C++ i XAML.

[!UWAGA]

Można użyć Równoległych wzorów biblioteki (PPL) i Biblioteka agentów asynchroniczne w Windows Store aplikacji.Nie można jednak używać harmonogramu zadań lub zasobów.Ten dokument zawiera opis dodatkowych funkcji, które zawiera aparat plików wykonywalnych współbieżności, które są dostępne tylko dla Windows Store aplikacji, a nie do aplikacji pulpitu.

Najważniejsze kwestie

  • Użycie concurrency::create_async do tworzenia operacji asynchronicznych, które mogą być używane przez inne składniki (które mogą być napisane w językach innych niż C++).

  • Użycie concurrency::progress_reporter do raportu postęp powiadomienia do składników, które wywołują swoje operacji asynchronicznych.

  • Anulowanie tokeny służy do włączania wewnętrznych operacji asynchronicznych anulować.

  • Zachowanie create_async funkcji zależy od zwracany typ funkcji pracy, który jest przekazywany do niego.Funkcja pracy, która zwraca zadania (albo task<T> lub task<void>) jest uruchamiana synchronicznie, w kontekście, który wywołał create_async.Funkcja pracy, która zwraca T lub void jest uruchamiany w kontekście dowolnego.

  • Można użyć concurrency::task::then metoda tworzenia łańcucha zadań, które są uruchamiane po kolei.W Windows Store aplikacji, domyślny kontekst dla kontynuacji zadania zależy sposób została skonstruowana tego zadania.Jeśli zadanie zostało utworzone przez przekazanie akcja asynchroniczna do konstruktora zadań lub przez przekazanie wyrażenia lambda zwracającą akcja asynchroniczna, domyślny kontekst dla wszystkich kontynuacji danego zadania jest bieżący kontekst.Jeśli zadanie nie składa się z poziomu operacji asynchronicznych, dowolnego kontekstu jest używany domyślnie dla kontynuacji zadania.Można zastąpić domyślny kontekst z concurrency::task_continuation_context klasy.

W tym dokumencie

  • Tworzenie operacji asynchronicznych

  • Przykład: Tworzenie składnika środowiska wykonawczego języka C++ systemu Windows

  • Kontrolowanie wątek wykonywania

  • Przykład: Sterowanie wykonywaniem w aplikacji magazynu systemu Windows z C++ i języka XAML

Tworzenie operacji asynchronicznych

Można użyć modelu zadanie i kontynuacji w równoległych Biblioteka wzorców (PPL) do definiowania zadania w tle, a także dodatkowe zadania, które są uruchamiane po zakończeniu poprzedniego zadania.Ta funkcja jest realizowana przez concurrency::task klasy.Aby uzyskać więcej informacji dotyczących tego modelu i task klasy, zobacz Zadanie równoległości (współbieżności Runtime).

Środowisko wykonawcze systemu Windows Jest interfejsem programowania, który służy do tworzenia Windows Store aplikacji, które działają tylko w środowisku specjalnego systemu operacyjnego.Takie aplikacje używać funkcji upoważniony, typy danych i urządzeń i są rozprowadzane z Windows Store.Środowisko wykonawcze systemu Windows Jest reprezentowana przez Interfejsu binarnego aplikacji (ABI).ABI jest podstawowym Umowa binarny, która sprawia, że Środowisko wykonawcze systemu Windows API dostępne dla języków programowania, takich jak Visual C++.

Za pomocą Środowisko wykonawcze systemu Windows, można użyć najlepszych funkcji w różnych językach programowania i połączyć je w jednej aplikacji.Na przykład może utworzyć swój interfejs użytkownika w języku JavaScript i wykonywania logiki aplikacji intensywnie obliczeniowo w składnika C++.Zdolność do wykonywania tych operacji obliczeniowo dużej ilości w tle jest kluczowym czynnikiem w utrzymaniu UI elastyczne.Ponieważ task klasy jest specyficzna dla języka C++, należy użyć Środowisko wykonawcze systemu Windows interfejs do komunikacji asynchronicznej operacji do innych składników (które mogą być napisane w językach innych niż C++).Środowisko wykonawcze systemu Windows Zawiera cztery interfejsy, które służą do reprezentowania operacji asynchronicznych:

Pojęcie akcji oznacza, że zadanie asynchroniczne nie mieć wartooć (Pomyśl o funkcję zwracającą void).Pojęcie operacji oznacza, że zadanie asynchroniczne uzyskiwania wartości.Pojęcie postępu oznacza zadanie zgłosić wiadomości postęp do obiektu wywołującego.JavaScript,.NET Framework i Visual C++ każdego zapewnia drogę do utworzenia wystąpienia tych interfejsów do użycia przez granicę ABI.Dla Visual C++ Runtime współbieżności zawiera concurrency::create_async funkcji.Ta funkcja tworzy Środowisko wykonawcze systemu Windows akcja asynchroniczna lub operacji, która reprezentuje ukończenie zadania.create_async Funkcja ma funkcję pracy (zazwyczaj Wyrażenie lambda), wewnętrznie tworzy task obiektu i zawija, które zadanie w jednym z czterech asynchroniczne Środowisko wykonawcze systemu Windows interfejsów.

[!UWAGA]

Użycie create_async , tylko kiedy należy utworzyć funkcje, które są dostępne z innego języka lub innego Środowisko wykonawcze systemu Windows składnika.Użycie task klasy bezpośrednio gdy wiesz, że operacja jest zarówno produkowane i konsumowane przez kod C++ w jednym składniku.

Zwracany typ create_async jest określane przez typ podanych argumentów.Na przykład, jeśli nasza funkcja pracy nie zwraca wartości, a nie raportują postępu create_async zwraca IAsyncAction.Jeśli nasza funkcja pracy nie zwraca wartości, a także raport o postępie, create_async zwraca IAsyncActionWithProgress.Aby raportować postęp, zapewnić concurrency::progress_reporter obiekt jako parametr do funkcji pracy.Możliwość raportowania postępu umożliwia raportowanie wykonano, jaka ilość pracy i co do ilości wciąż pozostaje (na przykład, jako procent).To pozwala również do raportowania wyników, w miarę ich udostępniania.

IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, I IAsyncActionOperationWithProgress<TProgress, TProgress> interfejs każdego dostarcza Cancel metodę, która pozwala anulować operacji asynchronicznej.task Klasy współpracuje z tokenów anulowania.Używając token odwołania do anulowania pracy, środowiska wykonawczego nie można uruchomić nowej pracy, które subskrybuje token.Pracy, które jest aktywne, można monitorować jego token odwołania i Zatrzymaj, gdy może.Mechanizm ten jest opisany bardziej szczegółowo w dokumencie Anulowanie w PPL.Można połączyć anulowanie zadania z Środowisko wykonawcze systemu WindowsCancel metody na dwa sposoby. Po pierwsze, można zdefiniować funkcję pracy, który jest przekazywany do create_async do podjęcia concurrency::cancellation_token obiektu.Gdy Cancel wywoływana jest metoda, token ten anulowania rezerwacji zostanie anulowana i reguły normalnej anulowania stosuje się do podstawowych task obiekt, który obsługuje create_async zadzwonić.Jeśli nie podasz cancellation_token obiektu, znajdujące się poniżej task obiekt definiuje jedną niejawnie.Definiowanie cancellation_token sprzeciwu, gdy musisz odpowiedzieć się wspólnie do odwołania w funkcji pracy.Sekcji przykład: kontrolowanie wykonania w aplikacji magazynu systemu Windows z C++ i XAML pokazuje przykład sposobu wykonywania anulowania w Windows Store aplikacji z C# i języka XAML, który korzysta z niestandardowego Środowisko wykonawcze systemu Windows składnika C++.

Informacje dotyczące przestrogiPrzestroga

W łańcuchu kontynuacji zadań, zawsze oczyścić stan, a następnie wywołać concurrency::cancel_current_task po concurrency::is_task_cancellation_requested zwraca true.Jeśli wrócić wcześnie zamiast telefonicznej cancel_current_task, przejścia do operacji do zadań ukończonych zamiast stan anulowane.

W następującej tabeli podsumowano kombinacji, które służy do definiowania operacji asynchronicznych w danej aplikacji.

Aby utworzyć ten Środowisko wykonawcze systemu Windows interfejsu

Zwracać tego typu zcreate_async

Przekazać te typy parametrów do funkcji swojej pracy, należy użyć token odwołania niejawna

Przekazać te typy parametrów do funkcji swojej pracy, należy użyć token jawne odwołania

IAsyncAction

void lub task<void>

(Brak)

(cancellation_token)

IAsyncActionWithProgress<TProgress>

void lub task<void>

(progress_reporter)

(progress_reporter, cancellation_token)

IAsyncOperation<TResult>

T lub task<T>

(Brak)

(cancellation_token)

IAsyncActionOperationWithProgress<TProgress, TProgress>

T lub task<T>

(progress_reporter)

(progress_reporter, cancellation_token)

Można zwrócić wartooć lub task obiekt z funkcji pracy, który jest przekazywany do create_async funkcji.Wahania te wytwarzają różne zachowania.Po powrocie wartość pracy wyjścia zapakowane jest w task , dzięki czemu może być uruchamiany na wątek w tle.Ponadto, znajdujące się poniżej task używa token niejawna anulowania.I odwrotnie jeśli powrócisz task obiektu, funkcja pracy jest uruchamiana synchronicznie.W związku z tym Jeśli powrócisz task obiekt, upewnij się, wszelkie długie w funkcji pracy również działanie operacji jako zadania, aby włączyć aplikację zapewniać możliwość reagowania.Ponadto, znajdujące się poniżej task nie używa token niejawna anulowania.W związku z tym, należy zdefiniować naszą funkcję Praca zaczęła cancellation_token obiektu, jeśli jest wymagana obsługa odwołania po powrocie task obiekt z create_async.

W poniższym przykładzie pokazano różne sposoby tworzenia IAsyncAction obiektów, które mogą być spożywane przez innego Środowisko wykonawcze systemu Windows składnika.

// Creates an IAsyncAction object and uses an implicit cancellation token.
auto op1 = create_async([]
{
    // Define work here.
});

// Creates an IAsyncAction object and uses no cancellation token.
auto op2 = create_async([]
{
    return create_task([]
    {
        // Define work here.
    });
});

// Creates an IAsyncAction object and uses an explicit cancellation token.
auto op3 = create_async([](cancellation_token ct)
{
    // Define work here.
});

// Creates an IAsyncAction object that runs another task and also uses an explicit cancellation token.
auto op4 = create_async([](cancellation_token ct)
{
    return create_task([ct]()
    {
        // Define work here.
    });
});

Top

Przykład: Tworzenie składnika środowiska wykonawczego języka C++ systemu Windows i jego spożywania z C#

Należy rozważyć aplikacji korzystającej z języka XAML i C# define interfejsu użytkownika i C++ Środowisko wykonawcze systemu Windows składnika do wykonywania operacji obliczeniowych.W tym przykładzie składnik C++ oblicza, które numery w danym zakresie są Premier.Aby zilustrować różnice między cztery Środowisko wykonawcze systemu Windows zadanie asynchroniczne interfejsów, uruchomić, w programie Visual Studio, tworząc Roztwór próby ślepej i nadając mu nazwę liczb pierwszych.Następnie dodać do roztworu Składnika systemu Windows w czasie wykonywania projektu i nadając mu nazwę PrimesLibrary.Dodaj następujący kod wygenerowany plik nagłówka C++ (ten przykład zmienia nazwę Class1.h do Primes.h).Każdy public metoda definiuje jeden z czterech interfejsów asynchronicznego.Metody, które zwracają wartość zwracają Windows::Foundation::Collections::IVector <int> obiektu.Metody, które raportują postępu produkcji double wartości, które definiują procent ilości pracy całkowitej, która została zakończona.

#pragma once

namespace PrimesLibrary
{
    public ref class Primes sealed
    {
    public:
        Primes();

        // Computes the numbers that are prime in the provided range and stores them in an internal variable.
        Windows::Foundation::IAsyncAction^ ComputePrimesAsync(int first, int last);

        // Computes the numbers that are prime in the provided range and stores them in an internal variable.
        // This version also reports progress messages.
        Windows::Foundation::IAsyncActionWithProgress<double>^ ComputePrimesWithProgressAsync(int first, int last);

        // Gets the numbers that are prime in the provided range.
        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<int>^>^ GetPrimesAsync(int first, int last);

        // Gets the numbers that are prime in the provided range. This version also reports progress messages.
        Windows::Foundation::IAsyncOperationWithProgress<Windows::Foundation::Collections::IVector<int>^, double>^ GetPrimesWithProgressAsync(int first, int last);
    };
}

[!UWAGA]

Umownie, metod asynchronicznych nazwy w Środowisko wykonawcze systemu Windows zazwyczaj kończą "Async".

Dodaj następujący kod w wygenerowanym pliku źródłowym C++ (ten przykład zmienia nazwę Class1.cpp do Primes.cpp).is_prime Funkcja określa, czy jego wprowadzania jest pierwsza.Pozostałe metody wdrożenia Primes klasy.Każde wywołanie create_async używa podpis, która jest zgodna z metodą, z którego nazywa się.Na przykład ponieważ Primes::ComputePrimesAsync zwraca IAsyncAction, funkcja pracy, dostarczanych do create_async nie zwraca wartości i nie bierze progress_reporter obiekt jako parametr.

// PrimesLibrary.cpp
#include "pch.h"
#include "Primes.h"
#include <atomic>
#include <collection.h>
#include <ppltasks.h>
#include <concurrent_vector.h>

using namespace concurrency;
using namespace std;

using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;

using namespace PrimesLibrary;

Primes::Primes()
{
}

// Determines whether the input value is prime. 
bool is_prime(int n)
{
    if (n < 2)
    {
        return false;
    }
    for (int i = 2; i < n; ++i)
    {
        if ((n % i) == 0)
        {
            return false;
        }
    }
    return true;
}

// Adds the numbers that are prime in the provided range  
// to the primes global variable.
IAsyncAction^ Primes::ComputePrimesAsync(int first, int last)
{
    return create_async([this, first, last]
    {
        // Ensure that the input values are in range. 
        if (first < 0 || last < 0)
        {
            throw ref new InvalidArgumentException();
        }
        // Perform the computation in parallel.
        parallel_for(first, last + 1, [this](int n)
        {
            if (is_prime(n))
            {
                // Perhaps store the value somewhere...
            }
        });
    });
}

IAsyncActionWithProgress<double>^ Primes::ComputePrimesWithProgressAsync(int first, int last)
{
    return create_async([first, last](progress_reporter<double> reporter)
    {
        // Ensure that the input values are in range.
        if (first < 0 || last < 0)
        {
            throw ref new InvalidArgumentException();
        }
        // Perform the computation in parallel. 
        atomic<long> operation = 0;
        long range = last - first + 1;
        double lastPercent = 0.0;
        parallel_for(first, last + 1, [&operation, range, &lastPercent, reporter](int n)
        {
            // Report progress message.
            double progress = 100.0 * (++operation) / range;
            if (progress >= lastPercent)
            {
                reporter.report(progress);
                lastPercent += 1.0;
            }

            if (is_prime(n))
            {
                // Perhaps store the value somewhere...
            }
        });
        reporter.report(100.0);
    });
}

IAsyncOperation<IVector<int>^>^ Primes::GetPrimesAsync(int first, int last)
{
    return create_async([this, first, last]() -> IVector<int>^
    {
        // Ensure that the input values are in range. 
        if (first < 0 || last < 0)
        {
            throw ref new InvalidArgumentException();
        }
        // Perform the computation in parallel.
        concurrent_vector<int> primes;
        parallel_for(first, last + 1, [this, &primes](int n)
        {
            // If the value is prime, add it to the global vector.
            if (is_prime(n))
            {
                primes.push_back(n);
            }
        });
        // Sort the results.
        sort(begin(primes), end(primes), less<int>());

        // Copy the results to an IVector object. The IVector 
        // interface makes collections of data available to other 
        // Windows Runtime components.
        auto results = ref new Vector<int>();
        for (int prime : primes)
        {
            results->Append(prime);
        }
        return results;
    });
}

IAsyncOperationWithProgress<IVector<int>^, double>^ Primes::GetPrimesWithProgressAsync(int first, int last)
{
    return create_async([this, first, last](progress_reporter<double> reporter) -> IVector<int>^
    {
        // Ensure that the input values are in range.
        if (first < 0 || last < 0)
        {
            throw ref new InvalidArgumentException();
        }
        // Perform the computation in parallel.
        concurrent_vector<int> primes;
        long operation = 0;
        long range = last - first + 1;
        double lastPercent = 0.0;
        parallel_for(first, last + 1, [&primes, &operation, range, &lastPercent, reporter](int n)
        {
            // Report progress message.
            double progress = 100.0 * (++operation) / range;
            if (progress >= lastPercent)
            {
                reporter.report(progress);
                lastPercent += 1.0;
            }

            // If the value is prime, add it to the local vector. 
            if (is_prime(n))
            {
                primes.push_back(n);
            }
        });
        reporter.report(100.0);

        // Sort the results.
        sort(begin(primes), end(primes), less<int>());

        // Copy the results to an IVector object. The IVector 
        // interface makes collections of data available to other 
        // Windows Runtime components.
        auto results = ref new Vector<int>();
        for (int prime : primes)
        {
            results->Append(prime);
        }
        return results;
    });
}

Każdą z tych metod najpierw wykonuje sprawdzanie poprawności, aby zapewnić, że że parametry wejściowe są ujemna.Jeśli wartość jest liczbą ujemną, metoda wygeneruje Platform::InvalidArgumentException.Obsługa błędów jest wyjaśnione później w tej sekcji.

Do spożywania tych metod z Windows Store aplikacji, użyj Visual C# App puste (XAML) szablon, aby dodać drugi projekt rozwiązania Visual Studio.W tym przykładzie nazwy projektu liczb pierwszych.Następnie, od liczb pierwszych projektu, Dodaj odwołanie do PrimesLibrary projektu.

Dodaj następujący kod do MainPage.xaml.Ten kod zawiera definicję interfejsu użytkownika tak, że można wywołać składnik C++ i wyświetlić wyniki.

<Page
    x:Class="Primes.MainPage"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Primes"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition Width="300"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="125"/>
            <RowDefinition Height="125"/>
            <RowDefinition Height="125"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Column="0" Grid.Row="0">
            <Button Name="b1" Click="computePrimes">Compute Primes</Button>
            <TextBlock Name="tb1"></TextBlock>
        </StackPanel>

        <StackPanel Grid.Column="1" Grid.Row="0">
            <Button Name="b2" Click="computePrimesWithProgress">Compute Primes with Progress</Button>
            <ProgressBar Name="pb1" HorizontalAlignment="Left" Width="100"></ProgressBar>
            <TextBlock Name="tb2"></TextBlock>
        </StackPanel>

        <StackPanel Grid.Column="0" Grid.Row="1">
            <Button Name="b3" Click="getPrimes">Get Primes</Button>
            <TextBlock Name="tb3"></TextBlock>
        </StackPanel>

        <StackPanel Grid.Column="1" Grid.Row="1">
            <Button Name="b4" Click="getPrimesWithProgress">Get Primes with Progress</Button>
            <ProgressBar Name="pb4"  HorizontalAlignment="Left" Width="100"></ProgressBar>
            <TextBlock Name="tb4"></TextBlock>
        </StackPanel>

        <StackPanel Grid.Column="0" Grid.Row="2">
            <Button Name="b5" Click="getPrimesHandleErrors">Get Primes and Handle Errors</Button>
            <ProgressBar Name="pb5"  HorizontalAlignment="Left" Width="100"></ProgressBar>
            <TextBlock Name="tb5"></TextBlock>
        </StackPanel>

        <StackPanel Grid.Column="1" Grid.Row="2">
            <Button Name="b6" Click="getPrimesCancellation">Get Primes with Cancellation</Button>
            <Button Name="cancelButton" Click="cancelGetPrimes" IsEnabled="false">Cancel</Button>
            <ProgressBar Name="pb6"  HorizontalAlignment="Left" Width="100"></ProgressBar>
            <TextBlock Name="tb6"></TextBlock>
        </StackPanel>
    </Grid>
</Page>

Dodaj następujący kod do MainPage klasy w MainPage.xaml.Ten kod zawiera definicję Primes obiektu i programy obsługi zdarzeń przycisku.

private PrimesLibrary.Primes primesLib = new PrimesLibrary.Primes();

private async void computePrimes(object sender, RoutedEventArgs e)
{
    b1.IsEnabled = false;
    tb1.Text = "Working...";

    var asyncAction = primesLib.ComputePrimesAsync(0, 100000);

    await asyncAction;

    tb1.Text = "Done";
    b1.IsEnabled = true;
}

private async void computePrimesWithProgress(object sender, RoutedEventArgs e)
{
    b2.IsEnabled = false;
    tb2.Text = "Working...";

    var asyncAction = primesLib.ComputePrimesWithProgressAsync(0, 100000);
    asyncAction.Progress = new AsyncActionProgressHandler<double>((action, progress) =>
    {
        pb1.Value = progress;
    });

    await asyncAction;

    tb2.Text = "Done";
    b2.IsEnabled = true;
}

private async void getPrimes(object sender, RoutedEventArgs e)
{
    b3.IsEnabled = false;
    tb3.Text = "Working...";

    var asyncOperation = primesLib.GetPrimesAsync(0, 100000);

    await asyncOperation;

    tb3.Text = "Found " + asyncOperation.GetResults().Count + " primes";
    b3.IsEnabled = true;
}

private async void getPrimesWithProgress(object sender, RoutedEventArgs e)
{
    b4.IsEnabled = false;
    tb4.Text = "Working...";

    var asyncOperation = primesLib.GetPrimesWithProgressAsync(0, 100000);
    asyncOperation.Progress = new AsyncOperationProgressHandler<IList<int>, double>((operation, progress) =>
    {
        pb4.Value = progress;
    });

    await asyncOperation;

    tb4.Text = "Found " + asyncOperation.GetResults().Count + " primes";
    b4.IsEnabled = true;
}

private async void getPrimesHandleErrors(object sender, RoutedEventArgs e)
{
    b5.IsEnabled = false;
    tb5.Text = "Working...";

    var asyncOperation = primesLib.GetPrimesWithProgressAsync(-1000, 100000);
    asyncOperation.Progress = new AsyncOperationProgressHandler<IList<int>, double>((operation, progress) =>
    {
        pb5.Value = progress;
    });

    try
    {
        await asyncOperation;
        tb5.Text = "Found " + asyncOperation.GetResults().Count + " primes";
    }
    catch (ArgumentException ex)
    {
        tb5.Text = "ERROR: " + ex.Message;
    }

    b5.IsEnabled = true;
}

private IAsyncOperationWithProgress<IList<int>, double> asyncCancelableOperation;

private async void getPrimesCancellation(object sender, RoutedEventArgs e)
{
    b6.IsEnabled = false;
    cancelButton.IsEnabled = true;
    tb6.Text = "Working...";

    asyncCancelableOperation = primesLib.GetPrimesWithProgressAsync(0, 200000);
    asyncCancelableOperation.Progress = new AsyncOperationProgressHandler<IList<int>, double>((operation, progress) =>
    {
        pb6.Value = progress;
    });

    try
    {
        await asyncCancelableOperation;
        tb6.Text = "Found " + asyncCancelableOperation.GetResults().Count + " primes";
    }
    catch (System.Threading.Tasks.TaskCanceledException)
    {
        tb6.Text = "Operation canceled";
    }

    b6.IsEnabled = true;
    cancelButton.IsEnabled = false;
}

private void cancelGetPrimes(object sender, RoutedEventArgs e)
{
    cancelButton.IsEnabled = false;
    asyncCancelableOperation.Cancel();
}

Użyj tych metod async i await słowa kluczowe, aby zaktualizować interfejsu użytkownika, po zakończeniu operacji asynchronicznych.Aby uzyskać informacje dotyczące wzorców asynchronicznych, które są dostępne dla języka C# i Visual Basic, zobacz asynchronicznego wzorców w magazynie systemu Windows aplikacji C# i asynchronicznego wzorców w aplikacji magazynu systemu Windows z VB.

getPrimesCancellation i cancelGetPrimes metody współpracować, aby umożliwić użytkownikowi anulować operację.Kiedy użytkownik zdecyduje się na anulowanie przycisku, cancelGetPrimes wywołania metody IAsyncOperationWithProgress < TResult, TProgress >:: anulowanie Aby anulować operację.Runtime współbieżności, która zarządza podstawowych operacji asynchronicznej, rzuca typu wyjątek wewnętrzny, który zostanie przechwycony przez Środowisko wykonawcze systemu Windows do komunikowania się, że Zakończono operację anulowania.Aby uzyskać więcej informacji na temat modelu anulowania, zobacz Anulowanie w PPL.

Ważna uwagaWażne

Aby włączyć w czasie wykonywania współbieżności prawidłowo zgłosić do Środowisko wykonawcze systemu Windows to, że została przez anulowana operacji, nie przechwytywać tego typu wyjątek wewnętrzny.Oznacza to, że użytkownik powinien również nie przechwytywać wszystkie wyjątki (catch (...)).Jeśli musisz przechwytywać wszystkie wyjątki, ponowne zgłoszenie wyjątku w celu zapewnienia, że Środowisko wykonawcze systemu Windows można ukończyć operacji anulowania.

Na poniższej ilustracji przedstawiono liczb pierwszych aplikacji po każdej z opcji został wybrany.

Aplikacja liczb pierwszych magazynu systemu Windows

Przykłady, które używają create_async Aby utworzyć zadania asynchroniczne, które mogą być spożywane przez innych języków, zobacz Przy użyciu języka C++ w próbce Bing Maps podróży służbowej Optymalizator i Operacji asynchronicznych 8 systemu Windows w języku C++ z PPL.

Top

Kontrolowanie wątek wykonywania

Środowisko wykonawcze systemu Windows Korzysta z modelu COM model wątków.W tym modelu obiektów znajdujących się w różnych apartamenty, w zależności od tego, jak poradzić sobie ich synchronizacji.Odporna na wielowątkowość obiektów znajdujących się w wielowątkowej (MTA).Obiekty, które muszą być udostępniane przez pojedynczy wątek znajdujących się w jednowątkowym apartamencie (STA).

W aplikacji, które ma interfejs użytkownika wątek ASTA (STA aplikacji) jest odpowiedzialny za pompowania komunikatów okien i jest jedynym wątkiem w procesie, który można aktualizować gospodarzem STA interfejsu użytkownika.Ma dwie konsekwencje.Po pierwsze aby umożliwić aplikacji zapewniać możliwość reagowania, wszystkie obliczeniowej i operacji We/Wy powinna nie można uruchamiać na wątku ASTA.Po drugie wyniki, które pochodzą z wątków w tle musi być organizowany powrót do ASTA, aby zaktualizować interfejsu użytkownika.W C++ Windows Store aplikacji, MainPage i inne strony XAML wszystkie uruchomione na ATSA.W związku z tym kontynuacji zadania, które są zadeklarowane w ASTY są tam domyślnie uruchamiane pozwala aktualizować formantów bezpośrednio w treści kontynuacji.Jeśli jednak możesz zagnieździć zadania w innym zadaniem, wszelkie kontynuacji na temat danego zadania zagnieżdżonych uruchomić w MTA.W związku z tym należy wziąć pod uwagę, czy należy jawnie określić, na jakie kontekst Uruchom te kontynuacji.

Zadania, utworzony na podstawie operacji asynchronicznej, takich jak IAsyncOperation<TResult>, semantyka specjalnych zastosowań, które mogą pomóc ignorować szczegóły wątka.Chociaż operacji mogą być uruchamiane w wątek w tle (lub go nie może być wspierane przez wątek w ogóle), jego kontynuacji są domyślnie gwarantowana do uruchamiania na mieszkanie, które rozpoczęły działalność kontynuacji (innymi słowy, z mieszkania, który wywołał task::then).Można użyć concurrency::task_continuation_context klasy do kontrolowania kontekstu wykonania utrzymania.Służy do tworzenia tych metod statyczna task_continuation_context obiektów:

Można przekazać task_continuation_context sprzeciwić się task::then metoda jawnie kontrolowania kontekst wykonywania kontynuacji lub użytkownik może przekazać zadanie do innego mieszkania, a następnie wywołać task::then metoda niejawnie kontrolowania kontekstu wykonania.

Ważna uwagaWażne

Ponieważ główny wątek interfejsu użytkownika Windows Store aplikacje uruchamiane w STA, kontynuacji, utworzone na tym STA domyślnie uruchomić na STA.W związku z tym kontynuacji, które zostaną utworzone MTA uruchomić MTA.

W poniższej sekcji przedstawiono aplikacji, które odczytuje plik z dysku, znajduje najczęściej używane wyrazy w tym pliku, a następnie wyświetla wyniki w interfejsie użytkownika.Ostatniej operacji, aktualizowanie interfejsu użytkownika, pojawia się w wątku interfejsu użytkownika.

Ważna uwagaWażne

To zachowanie jest specyficzny dla Windows Store aplikacji.W przypadku aplikacji nie kontroli, której kontynuacji jest uruchomiony.Zamiast tego harmonogramu wybiera wątek roboczy, na którym ma działać każdego kontynuacji.

Ważna uwagaWażne

Nie wywołuj concurrency::task::wait w organizmie utrzymania, które działa na STA.W przeciwnym wypadku zgłasza środowiska wykonawczego concurrency::invalid_operation ponieważ metoda ta blokuje bieżącego wątku i może spowodować, że aplikacja przestanie odpowiadać.Jednakże można wywołać concurrency::task::get metoda uzyskania wynik zadania antecedent kontynuację związanych z zadaniami.

Top

Przykład: Sterowanie wykonywaniem w Windows Store aplikacji z C++ i języka XAML

Należy rozważyć app C++ XAML, który odczytuje plik z dysku, znajduje najczęściej używane wyrazy w tym pliku, a następnie wyświetla wyniki w interfejsie użytkownika.Aby utworzyć tej aplikacji, uruchamianie, w Visual Studio, tworząc Windows StoreApp puste (XAML) projektu i nadając mu nazwę CommonWords. W manifeście aplikacji, należy określić Biblioteki Dokumenty zdolności, aby umożliwić aplikacji dostępu do folderu dokumenty.Typ pliku tekstowego (.txt) należy również dodać do sekcji deklaracji manifest aplikacji.Aby uzyskać więcej informacji o możliwościach aplikacji i deklaracje, zobacz pakietów aplikacji i wdrażania.

Aktualizacja Grid element w MainPage.xaml w celu włączenia ProgressRing element i TextBlock element.ProgressRing Wskazuje, że operacja jest w toku i TextBlock pokazuje wyniki obliczeń.

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <ProgressRing x:Name="Progress"/>
    <TextBlock x:Name="Results" FontSize="16"/>
</Grid>

Dodaj następujący #include instrukcji, aby pch.h.

#include <sstream>
#include <ppltasks.h>
#include <concurrent_unordered_map.h>

Dodaj następujące deklaracje metod, aby MainPage klasy (MainPage.h).

private:
    // Splits the provided text string into individual words.
    concurrency::task<std::vector<std::wstring>> MakeWordList(Platform::String^ text);

    // Finds the most common words that are at least the provided minimum length.
    concurrency::task<std::vector<std::pair<std::wstring, size_t>>> FindCommonWords(const std::vector<std::wstring>& words, size_t min_length, size_t count);

    // Shows the most common words on the UI.
    void ShowResults(const std::vector<std::pair<std::wstring, size_t>>& commonWords);

Dodaj następujący using instrukcji, aby MainPage.cpp.

using namespace concurrency;
using namespace std;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;

W MainPage.cpp, wdrożyć MainPage::MakeWordList, MainPage::FindCommonWords, i MainPage::ShowResults metody.MainPage::MakeWordList i MainPage::FindCommonWords wykonywania operacji obliczeniowo dużej ilości.MainPage::ShowResults Metoda wyświetla wynik obliczenia w interfejsie użytkownika.

// Splits the provided text string into individual words.
task<vector<wstring>> MainPage::MakeWordList(String^ text)
{
    return create_task([text]() -> vector<wstring>
    {
        vector<wstring> words;

        // Add continuous sequences of alphanumeric characters to the string vector.
        wstring current_word;
        for (wchar_t ch : text)
        {
            if (!iswalnum(ch))
            {
                if (current_word.length() > 0)
                {
                    words.push_back(current_word);
                    current_word.clear();
                }
            }
            else
            {
                current_word += ch;
            }
        }

        return words;
    });
}

// Finds the most common words that are at least the provided minimum length.
task<vector<pair<wstring, size_t>>> MainPage::FindCommonWords(const vector<wstring>& words, size_t min_length, size_t count)
{
    return create_task([words, min_length, count]() -> vector<pair<wstring, size_t>>
    {
        typedef pair<wstring, size_t> pair;

        // Counts the occurrences of each word.
        concurrent_unordered_map<wstring, size_t> counts;

        parallel_for_each(begin(words), end(words), [&counts, min_length](const wstring& word)
        {
            // Increment the count of words that are at least the minimum length. 
            if (word.length() >= min_length)
            {
                // Increment the count.
                InterlockedIncrement(&counts[word]);
            }
        });

        // Copy the contents of the map to a vector and sort the vector by the number of occurrences of each word.
        vector<pair> wordvector;
        copy(begin(counts), end(counts), back_inserter(wordvector));

        sort(begin(wordvector), end(wordvector), [](const pair& x, const pair& y)
        {
            return x.second > y.second;
        });

        size_t size = min(wordvector.size(), count);
        wordvector.erase(begin(wordvector) + size, end(wordvector));

        return wordvector;
    });
}

// Shows the most common words on the UI. 
void MainPage::ShowResults(const vector<pair<wstring, size_t>>& commonWords)
{
    wstringstream ss;
    ss << "The most common words that have five or more letters are:";
    for (auto commonWord : commonWords)
    {
        ss << endl << commonWord.first << L" (" << commonWord.second << L')';
    }

    // Update the UI.
    Results->Text = ref new String(ss.str().c_str());
}

Modyfikowanie MainPage Konstruktor do utworzenia łańcucha kontynuacji zadania, którym są wyświetlane w interfejsie użytkownika popularnych wyrazów w książce Iliady przez Homera.Pierwszego zadania dwóch kontynuacji, które podzielić tekst na pojedyncze wyrazy i znaleźć powszechnie używanych wyrazów, może być czasochłonne i dlatego są jawnie ustawione na uruchamianie w tle.Zadania końcowego kontynuacji, które aktualizacje interfejsu użytkownika, Określa kontekst nie kontynuacji, a w związku z powyższym apartment threading reguł.

MainPage::MainPage()
{
    InitializeComponent();

    // To run this example, save the contents of http://www.gutenberg.org/files/6130/6130-0.txt to your Documents folder.
    // Name the file "The Iliad.txt" and save it under UTF-8 encoding.

    // Enable the progress ring.
    Progress->IsActive = true;

    // Find the most common words in the book "The Iliad".

    // Get the file.
    create_task(KnownFolders::DocumentsLibrary->GetFileAsync("The Iliad.txt")).then([](StorageFile^ file)
    {
        // Read the file text.
        return FileIO::ReadTextAsync(file, UnicodeEncoding::Utf8);

        // By default, all continuations from a Windows Runtime async operation run on the 
        // thread that calls task.then. Specify use_arbitrary to run this continuation 
        // on a background thread.
    }, task_continuation_context::use_arbitrary()).then([this](String^ file)
    {
        // Create a word list from the text.
        return MakeWordList(file);

        // By default, all continuations from a Windows Runtime async operation run on the 
        // thread that calls task.then. Specify use_arbitrary to run this continuation 
        // on a background thread.
    }, task_continuation_context::use_arbitrary()).then([this](vector<wstring> words)
    {
        // Find the most common words.
        return FindCommonWords(words, 5, 9);

        // By default, all continuations from a Windows Runtime async operation run on the 
        // thread that calls task.then. Specify use_arbitrary to run this continuation 
        // on a background thread.
    }, task_continuation_context::use_arbitrary()).then([this](vector<pair<wstring, size_t>> commonWords)
    {
        // Stop the progress ring.
        Progress->IsActive = false;

        // Show the results.
        ShowResults(commonWords);

        // We don't specify a continuation context here because we want the continuation 
        // to run on the STA thread.
    });
}

[!UWAGA]

W tym przykładzie pokazano, jak określić kontekstów wykonanie i jak komponować łańcuch kontynuacji.Przypomnieć, że domyślnie uruchamiany przez zadanie utworzony na podstawie operację asynchroniczną jego kontynuacji na mieszkanie, który wywołał task::then.W związku z tym, w tym przykładzie użyto task_continuation_context::use_arbitrary do określenia, że wątek tła można wykonać operacji, które nie obejmują interfejsu użytkownika.

Na poniższej ilustracji przedstawiono wyniki CommonWords aplikacji.

Windows przechowywania aplikacji CommonWords

W tym przykładzie istnieje możliwość obsługuje anulowania, ponieważ task obiektów, które obsługują create_async użycie tokenu niejawna anulowania.Zdefiniuj swoje przez funkcję pracy cancellation_token obiektu, jeśli zadań musiał odpowiadać na anulowanie w sposób współpracy.Aby uzyskać więcej informacji o unieważnieniu w PPL zobaczAnulowanie w PPL

Top

Zobacz też

Koncepcje

Współbieżność Runtime