Sdílet prostřednictvím


Vytváření asynchronních operací v jazyce C++ pro aplikace pro web Windows Store

Tento dokument popisuje některé klíčové body třeba vzít v úvahu při použití modulu Runtime souběžnosti k vytvoření asynchronních operací v Windows Store aplikace.

Využívání asynchronního programování je klíčovou součástí Windows Store aplikace modelu, protože umožňuje aplikace pro zajištění reagovat na vstup uživatele.Je možné spustit úlohu dlouho běžící bez blokování vlákna uživatelského rozhraní a obdržíte výsledky úlohy později.Také můžete zrušit úlohy a přijímat oznámení průběh jako úlohy spuštěné na pozadí.Dokument asynchronní programování v jazyce C++ poskytuje přehled o asynchronní vzor, který je k dispozici v jazyce Visual C++ k vytvoření Windows Store aplikace.Tento dokument je určena jak používat i vytvořit řetězce asynchronní prostředí Windows Runtime operace.Tato část popisuje, jak pomocí modulu Runtime souběžnosti vytvářet asynchronní operace, které může být používán jiným prostředí Windows Runtime součástí a jak určit, jak asynchronní pracovní spuštěn.Také vzít v úvahu při čtení asynchronního programování vzorky a tipy v Hilo (aplikace pro Windows Store pomocí jazyka C++ a XAML) a seznamte se s jak můžeme použít modul Runtime souběžnosti k implementaci asynchronních operací v Hilo, Windows Store aplikací pomocí jazyka C++ a XAML.

[!POZNÁMKA]

Můžete použít Parallel Library vzory (PPL) a Knihovna asynchronních agentů v Windows Store aplikace.Nelze však použít služby Plánovač úloh nebo správce prostředků.Tento dokument popisuje další funkce, které poskytuje modul Runtime souběžnosti, které jsou k dispozici pouze Windows Store aplikace a ne na klientské aplikace.

Klíčové body

  • Použití concurrency::create_async k vytvoření asynchronní operace, které lze použít jinými součástmi (které může být napsán v jiných jazyků než C++).

  • Použití concurrency::progress_reporter sestava průběhu oznámení pro součásti, které volají vaše asynchronní operace.

  • Chcete-li povolit interní asynchronních operací, chcete-li zrušit pomocí tokenů zrušení.

  • Chování create_async funkce závisí na návratový typ funkce práce, který je předán.Pracovní funkci, která vrátí úlohu (buď task<T> nebo task<void>) synchronně spuštěna v kontextu, který volal create_async.Pracovní funkci, která vrací T nebo void běží v libovolné kontextu.

  • Můžete použít concurrency::task::then metodu pro vytvoření řetězu úlohy, které spustí za sebou.V Windows Store aplikací, výchozí kontext pro pokračování úlohy závisí na tom, jak byl zkonstruován tohoto úkolu.Pokud byl úkol vytvořen předáním asynchronní akce konstruktoru úloh nebo předáním výrazu lambda, která vrací asynchronní akce, výchozí kontext pro všechny pokračování tohoto úkolu je aktuálního kontextu.Pokud je úloha není vytvořen z asynchronní akce, pak libovolný kontext se používá ve výchozím nastavení pro pokračování úlohy.Můžete přepsat výchozí kontext s concurrency::task_continuation_context třídy.

V tomto dokumentu

  • Vytváření asynchronních operací

  • Příklad: Vytvoření komponenty modulu Runtime Windows C++

  • Řízení prováděcího vlákna

  • Příklad: Řízení provádění v aplikaci pro Windows Store s použitím C++ a XAML

Vytváření asynchronních operací

Můžete modelu úloh a pokračování v paralelní vzory knihovny (PPL) k definování úlohy na pozadí, jakož i další úlohy, které spustí po dokončení předchozí úlohy.Tato funkce je poskytována concurrency::task třídy.Další informace o tomto modelu a task třídy naleznete v tématu Funkční paralelismus (Concurrency Runtime).

prostředí Windows Runtime Je programovací rozhraní, které můžete použít k vytvoření Windows Store aplikací, které běží pouze v prostředí speciální operačního systému.Tyto aplikace používat autorizované funkcí a datových typů a zařízení a jsou distribuovány z Windows Store. prostředí Windows Runtime Je reprezentována Binární rozhraní aplikace (ABI).ABI je základní binární smlouvy, který způsobí, že prostředí Windows Runtime rozhraní API, které jsou k dispozici pro programovací jazyky, jako je například Visual C++.

S použitím prostředí Windows Runtime, můžete použít nejlepší funkce aplikace různých programovacích jazycích a sloučit je do jedné aplikace.Můžete například vytvářet uživatelské rozhraní v jazyce JavaScript a provádět logiku rovněž velkými nároky na výkon aplikace v jazyce C++ součásti.Možnost provádět tyto operace rovněž náročné na pozadí je klíčový faktor udržování rychlými uživatelského rozhraní.Protože task Třída je specifické pro C++, je nutné použít prostředí Windows Runtime rozhraní pro komunikaci asynchronních operací na jiné součásti (které může být napsán v jiných jazyků než C++). prostředí Windows Runtime Poskytuje čtyři rozhraní, které můžete použít k reprezentování asynchronních operací:

Pojem Akce znamená, že není zaškrtnuta asynchronní úlohu vytvoření hodnoty (Představte si, že funkce, která vrací void).Pojem operace znamená, že asynchronní úlohu vytvoření hodnoty.Pojem Průběh znamená to, že úloha může odesílat zprávy o průběhu volajícího.JavaScript, rozhraní .NET Framework a Visual C++ poskytuje vlastní způsob pro vytvoření instance z těchto rozhraní pro použití přes hranice ABI.Pro Visual C++ Runtime souběžnosti poskytuje concurrency::create_async funkce.Tato funkce vytvoří prostředí Windows Runtime asynchronní akce nebo operaci, která představuje dokončení úkolu.create_async Funkce přebírá pracovní funkci (obvykle výrazu lambda), interně vytvoří task objektu a zabalí, které úlohy v jedné z asynchronní čtyři prostředí Windows Runtime rozhraní.

[!POZNÁMKA]

Použití create_async pouze v případě, je nutné vytvořit funkcí, které lze získat na jiném jazyce nebo jinou prostředí Windows Runtime součástí.Použití task třídy přímo když víte, že operace je vytvořen i spotřebovaného v kódu jazyka C++ do stejné komponenty.

Návratový typ create_async je určena typem argumentů.Pokud váš pracovní funkci nevrací hodnotu není sestavu a pokroku, například create_async vrátí IAsyncAction.Pokud váš pracovní funkce nevrací hodnotu a také oznámí pokroku, create_async vrátí IAsyncActionWithProgress.Chcete-li zprávy o průběhu, zadejte concurrency::progress_reporter objekt jako parametr funkce vaší práce.Možnost vykazovat postup umožňuje ohlásit, jaké množství práce byla provedena a jaká částka zůstane v počítači (například v procentech).Umožňuje také můžete do výsledků sestavy, jakmile budou k dispozici.

IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, A IAsyncActionOperationWithProgress<TProgress, TProgress> rozhraní každý poskytují Cancel metodu, která umožňuje zrušit asynchronní operaci.task Třída pracuje s tokenů zrušení.Použijete-li token zrušení pro zrušení práce, modul runtime nespustí nové práci, která se přihlásí k tento token.Práce, která je již aktivní můžete sledovat jeho token zrušení a zastavit, pokud je to možné.Tento mechanismus je popsán podrobněji v dokumentu Zrušení v knihovně PPL.Zrušení úlohy se můžete připojit prostředí Windows Runtime Cancel metody dvěma způsoby.First, můžete definovat práci funkce, která předáte create_async přijmout concurrency::cancellation_token objektu.Když Cancel Metoda je volána, bylo zrušeno tento token zrušení a normální zrušení pravidla platí pro základní task objekt, který podporuje create_async volání.Pokud nezadáte cancellation_token objektu, základní task objekt definuje jednu implicitně.Definovat cancellation_token objektu, pokud je potřeba spolupráci reagovat na zrušení ve vaší pracovní funkci.V části Příklad: řízení spuštění v aplikaci pro Windows Store s použitím C++ a XAML ukazuje příklad toho, jak provádět zrušení v Windows Store aplikací s C# a XAML, která používá vlastní prostředí Windows Runtime komponentu C++.

Poznámka k upozorněníUpozornění

V řetězci pokračování úlohy, vždy vyčistit stav a poté zavolá concurrency::cancel_current_task při concurrency::is_task_cancellation_requested vrátí true.Pokud se vrátíte rané fázi namísto volání metody cancel_current_task, přechody operace do dokončené stavu namísto zrušené stavu.

Následující tabulka shrnuje kombinace, které lze použít k definování asynchronních operací ve vaší aplikaci.

K vytvoření tohoto prostředí Windows Runtime rozhraní

Tento typ z návratového create_async

Předat své pracovní funkci použít token zrušení implicitní tyto typy parametrů

Předat své pracovní funkci použít token zrušení explicitní tyto typy parametrů

IAsyncAction

void nebo task<void>

(žádné)

(cancellation_token)

IAsyncActionWithProgress<TProgress>

void nebo task<void>

(progress_reporter)

(progress_reporter, cancellation_token)

IAsyncOperation<TResult>

T nebo task<T>

(žádné)

(cancellation_token)

IAsyncActionOperationWithProgress<TProgress, TProgress>

T nebo task<T>

(progress_reporter)

(progress_reporter, cancellation_token)

Může vrátit hodnotu nebo task objektu z pracovní funkce, která předáte create_async funkce.Tyto odchylky vytvořit odlišného chování.Při návratu hodnotu pracovní funkci je zabalena v task tak, aby ji lze spustit ve vlákně pozadí.Kromě toho základní task používá token implicitní zrušení.Naopak pokud se vrátíte task objekt, funkci pracovní pracuje synchronně.Proto pokud se vrátíte task objekt, ujistěte se, že žádné dlouhé operace ve vaší pracovní funkci také spustit jako úkoly, chcete-li povolit svou aplikaci pro zajištění reaguje.Kromě toho základní task nepoužívá token implicitní zrušení.Proto je třeba definovat vaší pracovní funkci přijmout cancellation_token objektu, pokud požadujete podporu pro zrušení při návratu task objekt z create_async.

Následující příklad ukazuje různých způsobů, jak vytvořit IAsyncAction objekt, který může být používán jiným prostředí Windows Runtime součástí.

// 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.
    });
});

[Nahoře]

Příklad: Vytvoření komponenty modulu Windows Runtime v jazyce C++ a její použití v jazyce C#

Zvažte aplikace, která se používá k definování uživatelského rozhraní a C++ XAML a C# prostředí Windows Runtime součástí provádět operace náročné na výkon.V tomto příkladu vypočte komponentu C++, která čísla v daném rozsahu jsou primárního.Pro ilustraci rozdíly mezi čtyři prostředí Windows Runtime rozhraní asynchronní úlohu spustit, v sadě Visual Studio vytvořením prázdné řešení a pojmenování ji si mosty.Poté přidat do řešení součásti systému Windows Runtime projektů a pojmenování ji PrimesLibrary.Přidejte následující kód do generovaného souboru hlaviček C++ (v tomto příkladu přejmenuje Class1.h na Primes.h).Každý public Metoda definuje jedno z čtyři asynchronní rozhraní.Vrátí metody, které vrací hodnotu Windows::Foundation::Collections::IVector < int > objektu.Vytvořit metody, které sestava průběhu double hodnoty, které definují procentuální hodnotu celkové práce, která byla dokončena.

#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);
    };
}

[!POZNÁMKA]

Podle konvence názvů asynchronní metody v prostředí Windows Runtime obvykle končit řetězcem "Asynchronní".

Přidejte následující kód (v tomto příkladu přejmenuje Class1.cpp na Primes.cpp) vygenerované zdrojový soubor jazyka C++.is_prime Funkce určuje, zda vstupní primárního.Zbývající metody implementovat Primes třídy.Každé volání create_async používá podpis, který je kompatibilní s metodě, ze kterého je volána.Můžete například vzhledem k tomu, Primes::ComputePrimesAsync vrátí IAsyncAction, pracovní funkci, která je k dispozici na create_async nevrací hodnotu a nelze provést progress_reporter objektu jako jeho 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á metoda nejprve provádí ověřování a ujistěte se, zda vstupní parametry jsou nezáporná.Pokud je vstupní hodnota záporná, vyvolá metoda Platform::InvalidArgumentException.Zpracování chyb je vysvětleno dále v této části.

Chcete-li používat tyto metody z Windows Store aplikace, používat Visual C# prázdné aplikace XAML () šablony přidat druhý projekt do řešení pro Visual Studio.V tomto příkladu názvy projektu si mosty.Potom z si mosty projektu, přidejte odkaz na PrimesLibrary projektu.

Přidejte následující kód do MainPage.xaml.Tento kód definuje uživatelského rozhraní, takže můžete volat komponentu C++ a zobrazit výsledky.

<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>

Přidat následující kód, který MainPage třídy v MainPage.xaml.Tento kód definuje Primes objektu a tlačítko obslužných rutin.

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();
}

Tyto metody používají async a await klíčových slov k aktualizaci uživatelského rozhraní, po dokončení asynchronní operace.Informace o asynchronní zpracování, které jsou k dispozici v jazyce C# a Visual Basic, naleznete v části asynchronní zpracování v aplikacích pro Windows Store s C# a asynchronní zpracování v aplikacích pro Windows Store pomocí jazyka Visual Basic.

getPrimesCancellation a cancelGetPrimes metody pracují společně, chcete-li povolit uživatele, kterého chcete-li operaci zrušit.Pokud uživatel zvolí zrušit tlačítko, cancelGetPrimes volání metody IAsyncOperationWithProgress < TResult, TProgress >:: zrušit na tlačítko Storno.Modul Runtime souběžnosti, která spravuje podkladové asynchronní operaci, vyvolá typ vnitřní výjimky, která bude zachycena prostředí Windows Runtime ke komunikaci, že zrušení bylo dokončeno.Další informace o zrušení modelu naleznete v tématu Zrušení v knihovně PPL.

Důležitá poznámkaDůležité

Chcete-li povolit modul Runtime souběžnosti správně zaznamenávané prostředí Windows Runtime dokáže zrušil operaci, není catch tento typ vnitřní výjimky.To znamená, že by neměl také zachytit všechny výjimky (catch (...)).Pokud musí zachytit všechny výjimky, úloha znovu vyvolat úlohy výjimka zajistit, aby prostředí Windows Runtime lze dokončit operaci zrušení.

Na následujícím obrázku je znázorněno si mosty aplikace po jednotlivých možností byl vybrán.

Aplikace pro Windows Store si mosty

Příklady, které používají create_async vytvoření asynchronní úlohy, které může být používán jinými jazyky naleznete v tématu pomocí jazyka C++ v ukázce Bing Maps cesty optimalizace a asynchronní operace systému Windows 8 v jazyce C++ s PPL.

[Nahoře]

Řízení prováděcího vlákna

prostředí Windows Runtime Používá model podprocesů modelu COM..V tomto modelu objekty jsou umístěny v různých bytů, v závislosti na tom, jak, které zpracovávají jejich synchronizace.Vláken objekty jsou umístěny v vícevláknové apartment (MTA).Objekty, které musí být jedno vlákno přistupuje jsou umístěny v jeden podproces apartment (STA).

V aplikaci, která má uživatelské rozhraní vlákno ASTA (aplikace STA) je zodpovědná za přidávání okna zprávy a je pouze vlákna v procesu, který lze aktualizovat ovládací prvky uživatelského rozhraní hostované STA.Tato akce nemá dva důsledky.Nejprve povolit aplikaci, aby zůstat rychlými, všechny náročné na využití procesoru a vstupně-výstupních operací by neměl spustit na ASTA vlákna.Druhý výsledky, které pocházejí z vlákna pozadí musí zařadit zpět na ASTA k aktualizaci uživatelského rozhraní.V C++ Windows Store aplikace, MainPage a jiné stránky XAML všechny spustit na ATSA.Proto pokračování úlohy, které jsou deklarovány na ASTA jsou spouštěny došlo ve výchozím nastavení tak můžete aktualizovat ovládací prvky přímo v pokračování textu.Pokud ale vnořit úkolu v jiném úkolu jakékoli pokračování na vnořené úlohu spustit v MTA.Proto je třeba zvážit, zda má být explicitně zadat na jaké kontextu spuštění tyto pokračování.

Úloha, která je vytvořeno na základě asynchronní operace, jako je například IAsyncOperation<TResult>, používá speciální sémantiku, které vám pomohou ignorovat podprocesů podrobnosti.Ačkoli může probíhat operace vláknem na pozadí (nebo ho nemusí být založených na vlákno vůbec), jeho pokračování jsou ve výchozím nastavení zaručena ke spuštění v apartment, které vytvořili pokračování operace (jinými slovy, z apartment, který volal task::then).Můžete použít concurrency::task_continuation_context třídy pro řízení kontextu spuštění pokračování.Pomocí těchto statické pomocné metody můžete vytvořit task_continuation_context objekty:

Můžete předat task_continuation_context objektu task::then můžete předat úloha na jiné apartment a poté zavolá metodu explicitně řízení kontextu spuštění pokračování nebo můžete task::then metodu implicitně řízení kontextu spuštění.

Důležitá poznámkaDůležité

Protože hlavní vlákno uživatelského rozhraní Windows Store aplikace spuštěna pod STA, spusťte pokračování, které vytvoříte v tomto STA ve výchozím nastavení v STAVzhledem k tomu pokračování, které vytvoříte na MTA spustit na MTA.

V následující části ukazuje aplikace, která přečte soubor z disku, vyhledá nejběžnější slova v tomto souboru a poté se zobrazí výsledky v uživatelském rozhraní.Poslední operaci, Probíhá aktualizace uživatelského rozhraní, proběhne vlákna uživatelského rozhraní.

Důležitá poznámkaDůležité

Toto chování je specifické pro Windows Store aplikace.Pro klientské aplikace není určit, kde je spuštěn pokračování.Namísto toho plánovače zvolí pracovní podproces, na kterém mohou běžet každý pokračování.

Důležitá poznámkaDůležité

Nevolejte concurrency::task::wait v těle pokračování, které běží na STAJinak modul runtime vyvolá výjimku concurrency::invalid_operation, jelikož tato metoda blokuje aktuální vlákno a může způsobit, že aplikace přestane odpovídat.Nicméně lze pro získání výsledku předchozího úkolu v pokračování založeném na úkolech zavolat metodu concurrency::task::get.

[Nahoře]

Příklad: Řízení provádění v Windows Store aplikace s použitím C++ a XAML

Zvažte aplikace C++ XAML, který přečte soubor z disku, vyhledá nejběžnější slova v tomto souboru a poté se zobrazí výsledky v uživatelském rozhraní.Chcete-li vytvořit této aplikace, začněte, v sadě Visual Studio vytvořením Windows Store prázdné aplikace XAML () projektů a pojmenování ji CommonWords.V manifestu vaší aplikace, zadejte knihovny dokumentů schopností, chcete-li povolit aplikaci, aby přístup ke složce Dokumenty.Typ souboru Text (.txt) můžete také přidáte do části prohlášení manifest aplikace.Další informace o možnostech aplikace a deklarací naleznete v tématu balíčky aplikací a nasazení.

Aktualizace Grid element v MainPage.xaml tak, aby obsahoval ProgressRing elementu a TextBlock elementu.ProgressRing Znamená, že operace je v průběhu a TextBlock jsou zobrazeny výsledky výpočtu.

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

Přidejte následující #include tvrzení, která se pch.h.

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

Přidat následující prohlášení metoda, která MainPage třídy (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);

Přidejte následující using tvrzení, která se MainPage.cpp.

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

V MainPage.cpp, implementovat MainPage::MakeWordList, MainPage::FindCommonWords, a MainPage::ShowResults metody.MainPage::MakeWordList a MainPage::FindCommonWords provádět operace rovněž velkými nároky na výkon.MainPage::ShowResults Metoda zobrazí výsledek výpočtu v uživatelském rozhraní.

// 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());
}

Změnit MainPage konstruktor pro vytvoření řetězu pokračování úlohy, který se zobrazuje v uživatelském rozhraní běžná slova v knize The Iliad podle Homer.První dvě pokračování úkoly, které rozdělit text na jednotlivá slova a běžné slova, může být časově náročné a jsou proto explicitně nastaven na pozadí.Konečná pokračování úkol, který aktualizuje uživatelské rozhraní, určuje žádný kontext pokračování a proto dodržovat apartment práce s podprocesy pravidla.

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.
    });
}

[!POZNÁMKA]

Tento příklad ukazuje, jak určit kontext spuštění a jak napište řetězci pokračování.Odvolání, že ve výchozím nastavení úloha, která je vytvořeno na základě asynchronní operace běží jeho pokračování na apartment, která volá task::then.Proto v tomto příkladu task_continuation_context::use_arbitrary k určení, že operace, které neobsahují uživatelské rozhraní provést vláknem na pozadí.

Na následujícím obrázku jsou zobrazeny výsledky CommonWords aplikace.

CommonWords aplikací pro Windows Store

V tomto příkladu je možné podporovat zrušení, protože task objektů, které podporují create_async použít token implicitní zrušení.Definice funkce své pracovní přijmout cancellation_token objektu, pokud vaše úkoly nutné k reakci na zrušení spolupráce způsobem.Další informace o zrušení v PPL, naleznete v části Zrušení v knihovně PPL

[Nahoře]

Viz také

Koncepty

Concurrency Runtime