Tworzenie operacji asynchronicznych w języku C++ dla aplikacji sklepu Windows Store
W tym dokumencie opisano niektóre z kluczowych punktach mieć na uwadze, gdy do tworzenia operacji asynchronicznych w za pomocą środowiska wykonawczego współbieżności Windows Store aplikacji.
Korzystanie z programowanie asynchroniczne jest składnikiem klucza w Windows Store model aplikacji, ponieważ umożliwia on aplikacje pozostać odpowiadać na dane wejściowe użytkownika.Zadanie długim mogą być uruchamiane bez blokowania wątku interfejsu użytkownika, a usługa umożliwia otrzymywanie wyników zadanie później.Możesz również anulować zadania i otrzymywać powiadomienia o postępie jako zadania uruchomiony w tle.Dokument asynchronicznego programowania w języku C++ zawiera przegląd asynchroniczne deseń, który jest dostępny w programie Visual C++, aby utworzyć Windows Store aplikacji.Ten dokument zawiera wskazówki zarówno zużywać i tworzeniu łańcuchów asynchroniczne Środowisko wykonawcze systemu Windows operacji.W tej sekcji opisano sposób tworzenia operacji asynchronicznych, które mogą być używane przez inny za pomocą środowiska wykonawczego współbieżności Środowisko wykonawcze systemu Windows wykonaniu składników i kontrola jak zadanie asynchroniczne.Rozważ również odczytu programowania asynchronicznego wzorców i porady w Hilo (aplikacji ze Sklepu Windows za pomocą języka C++ i XAML) Aby dowiedzieć się, jak użyliśmy współbieżności środowisko uruchomieniowe służące do implementacji operacji asynchronicznych w Hilo, Windows Store aplikacji za pomocą języka C++ i XAML.
[!UWAGA]
Można użyć równoległe Biblioteka wzorców (PPL) i Biblioteka agentów asynchronicznych w Windows Store aplikacji.Nie można jednak użyć harmonogramu zadań lub Menedżera zasobów.Ten dokument zawiera informacje dodatkowe funkcje, które zapewnia środowisko uruchomieniowe współbieżności, które są dostępne tylko dla Windows Store aplikacji, a nie do aplikacji komputerowej.
Kwestie kluczowe
Użyj concurrency::create_async do utworzenia operacji asynchronicznych, które mogą być używane przez inne składniki (które mogą być zapisane w językach innych niż C++).
Użyj concurrency::progress_reporter raport postępu powiadomień do składników, które wywołują swoje operacji asynchronicznych.
Aby włączyć wewnętrzny operacji asynchronicznych anulować, należy użyć tokeny anulowania.
Zachowanie create_async funkcji zależy od typ zwrotny funkcji pracy, która została przekazana do niej.Funkcja pracy, która zwraca zadanie (albo task<T> lub task<void>) jest uruchamiana synchronicznie, w tym kontekście, który wywołał create_async.Funkcja pracy, która zwraca T lub void działa w kontekście umownego.
Można użyć concurrency::task::then metodę w celu utworzenia łańcucha zadania, które są uruchamiane po kolei.W Windows Store aplikację, domyślny kontekst dla zadania continuations zależy od jak został skonstruowany tego zadania.Jeśli zadanie zostało utworzone przez przekazanie akcja asynchroniczna do konstruktora zadań lub przez przekazanie wyrażenia lambda, który zwraca akcja asynchroniczna, domyślny kontekst dla wszystkich continuations tego zadania jest bieżącego kontekstu.Jeśli zadanie nie jest tworzony z akcji asynchronicznych, kontekst dowolnego jest używany w domyślnie dla continuations 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ątku wykonania
Przykład: Kontrolowanie wykonania w aplikacji ze Sklepu Windows w C++ i XAML
Tworzenie operacji asynchronicznych
Zadanie i kontynuacji model można użyć w równoległe Biblioteka wzorców (PPL) do definiowania zadania w tle, a także dodatkowe zadania, które są uruchamiane po ukończeniu poprzedniego zadania.Ta funkcja jest dostarczana przez concurrency::task klasy.Aby uzyskać więcej informacji na temat tego modelu i task zobacz Równoległość zadania (współbieżność środowiska wykonawczego).
Środowisko wykonawcze systemu Windows Jest interfejsem programowania, który służy do tworzenia Windows Store aplikacji działających tylko w środowisku specjalnych systemu operacyjnego.Takich aplikacji za pomocą funkcji autoryzowane, typy danych i urządzeń, a są rozpowszechniane z Windows Store. Środowisko wykonawcze systemu Windows Jest reprezentowany przez Binary interfejsu aplikacji (ABI).Źródłowego umowy binary, który sprawia, że jest ABI Środowisko wykonawcze systemu Windows interfejsów API dostępnych dla języków programowania, takich jak Visual C++.
Przy użyciu Środowisko wykonawcze systemu Windows, można korzystać z funkcji najlepsze w różnych językach programowania i połączyć je w jednej aplikacji.Na przykład możesz utworzyć interfejs użytkownika w języku JavaScript i wykonać logiki praktyce intensywnie korzysta z aplikacji w składniku C++.Możliwość wykonania tych operacji w praktyce intensywnie korzysta z w tle jest kluczowym czynnikiem zachowuje interaktywnych interfejs użytkownika.Ponieważ task Klasa jest specyficzne dla języka C++, należy użyć Środowisko wykonawcze systemu Windows interfejs służący do komunikacji asynchronicznej operacji do innych składników (które mogą być zapisane w językach innych niż C++). Środowisko wykonawcze systemu Windows Udostępnia cztery interfejsy, które służą do reprezentowania operacji asynchronicznych:
Windows::Foundation::IAsyncAction
Reprezentuje akcję asynchroniczną.Windows::Foundation::IAsyncActionWithProgress < TProgress >
Reprezentuje akcję asynchroniczną, która zgłasza postępu.Windows::Foundation::IAsyncOperation < TResult >
Reprezentuje operację asynchroniczną, która zwraca wynik.Windows::Foundation::IAsyncOperationWithProgress < TResult, TProgress >
Reprezentuje operację asynchroniczną, która zwraca wynik i raporty postępu.
Pojęcia akcji oznacza, że zadanie asynchroniczne nie zwróci wartość (reakcji funkcji, która zwraca void).Pojęcia operacji oznacza, że zadanie asynchroniczne utworzenia wartości.Pojęcia postępu oznacza zadanie można zgłosić komunikaty o postępie do obiektu wywołującego.JavaScript, .NET Framework i Visual C++ każdego udostępnia drodze do tworzenia wystąpień tych interfejsów do użycia na granicach ABI.Zapewnia środowisko uruchomieniowe współbieżności Visual C++, concurrency::create_async funkcji.Ta funkcja tworzy Środowisko wykonawcze systemu Windows Akcja asynchroniczna lub operację, która reprezentuje ukończenie zadania.create_async Funkcji pobierającej funkcja pracy (zazwyczaj wyrażenia lambda), wewnętrznego tworzy task obiektu i opakowujący, które zadania w jednym z czterech asynchroniczne Środowisko wykonawcze systemu Windows interfejsów.
[!UWAGA]
Użyj create_async tylko kiedy należy utworzyć funkcje, które są dostępne z innego języka lub innym Środowisko wykonawcze systemu Windows składników.Użyj task klasy bezpośrednio po wiesz, że operacja jest zarówno utworzone i używane przez kodu C++ w ten sam składnik.
Typ zwrotny create_async jest określana przez typ argumentów.Na przykład, jeśli funkcja pracy nie raport postępu i nie zwraca wartości create_async zwraca IAsyncAction.Funkcja pracy również raportami postępu, i nie zwraca wartości create_async zwraca IAsyncActionWithProgress.Aby zgłosić postępu, podaj concurrency::progress_reporter obiektu jako parametr do funkcji swoją pracę.Możliwość raportować postęp umożliwia zgłaszanie została wykonana, jaką ilość pracy i jakie ilości wciąż (na przykład w postaci wartości procentowej).Można również do wyniki raportu, gdy będą one dostępne.
IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, I IAsyncActionOperationWithProgress<TProgress, TProgress> świadczenia interfejsy każdego Cancel metody, która pozwala anulować operację asynchroniczną.task Klasa działa z tokenów anulowania.Korzystając z token anulowania do anulowania pracy, środowisko uruchomieniowe nie zaczyna się nowe dzieło, które subskrybuje token.Pracę, która jest już aktywna, można monitorować jego token anulowania i Zatrzymaj, gdy może.Ten mechanizm opisano szczegółowo w dokumencie Anulowanie w PPL.Można połączyć anulowania zadania z Środowisko wykonawcze systemu Windows Cancel metody na dwa sposoby.Po pierwsze, można zdefiniować przekazywany do funkcji pracy create_async do podjęcia concurrency::cancellation_token obiektu.Gdy Cancel Metoda jest wywoływana, ten token anulowania została anulowana i reguły anulowania normalny na odpowiedni task obiekt, który obsługuje create_async wywołania.Jeśli nie zostanie określona cancellation_token obiektu, odpowiedni task definiuje jedną niejawnie obiektu.Definiowanie cancellation_token obiektu, gdy istnieje potrzeba wspólnie odpowiadać anulowania w funkcji swoją pracę.Sekcja przykład: kontrolowanie wykonania w aplikacji do Sklepu Windows dzięki C++ i XAML przedstawiono sposób wykonywania anulowania w Windows Store aplikacji z C# i XAML, który używa niestandardowego Środowisko wykonawcze systemu Windows składnika C++.
Przestroga |
---|
W łańcuchu continuations zadanie, zawsze Wyczyść stan, a następnie wywołać concurrency::cancel_current_task po concurrency::is_task_cancellation_requested zwraca true.Jeśli powrócisz wczesnego zamiast wywołania metody cancel_current_task, przejścia do operacji zakończonych stan zamiast stan anulowane. |
Poniższa tabela zawiera podsumowanie kombinacje, które służą do definiowania operacji asynchronicznych w swojej aplikacji.
Aby utworzyć ten Środowisko wykonawcze systemu Windows interfejsu |
Zwraca tego typu z create_async |
Przekaż te typy parametrów funkcji swoją pracę do użycia token anulowania niejawne |
Przekaż te typy parametrów funkcji swoją pracę do użycia token anulowania jawne |
---|---|---|---|
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że zwracać wartość lub task obiekt przekazywany do funkcji pracy create_async funkcji.Te wersje produktu różne zachowania.Po powrocie wartość funkcji pracy jest opakowane w task Tak, aby można go uruchomić na wątek w tle.Ponadto odpowiedni task używa token anulowania niejawne.Z kolei jeśli powrócisz task obiektu, funkcja pracy jest uruchamiana synchronicznie.W związku z tym Jeśli powrócisz task obiektów, upewnij się, że wszystkie operacje długie w funkcji swojej pracy również uruchomić jako zadania umożliwiające pozostanie interaktywnych aplikacji.Ponadto odpowiedni task token anulowania niejawne nie są używane.W związku z tym, należy zdefiniować swoją przez funkcję pracy cancellation_token obiektu, jeśli wymagana obsługa anulowania po powrocie task obiektu z create_async.
W poniższym przykładzie pokazano różne sposoby tworzenia IAsyncAction obiektów, które mogą być używane przez innego Środowisko wykonawcze systemu Windows składników.
// 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.
});
});
[U góry]
Przykład: Tworzenie składnika C + + środowiska wykonawczego systemu Windows i jego wykorzystanie z C#
Należy rozważyć aplikację, która jest używana do definiowania interfejsu użytkownika i C++ XAML, jak i C# Środowisko wykonawcze systemu Windows składników do wykonywania operacji obliczeniowych.W tym przykładzie składnik C++ oblicza, które numery w podanym zakresie są głównego.Ilustrujące różnic między cztery Środowisko wykonawcze systemu Windows interfejsy zadanie asynchroniczne uruchomić, w programie Visual Studio, tworząc puste rozwiązanie jak i jej nazwy zapory.Następnie dodaj do rozwiązania składnik środowiska wykonawczego systemu Windows projektu i nadając mu nazwę PrimesLibrary.Dodaj następujący kod do pliku wygenerowany nagłówek C++ (w tym przykładzie zmienia nazwę Class1.h na Primes.h).Każdy public metody definiuje jeden z czterech interfejsów asynchronicznego.Metody, które zwracają wartości zwracają Windows::Foundation::Collections::IVector < int > obiektu.Metody raportować postęp tworzenia double wartości, które definiują procent całkowitej pracy, która została ukoń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]
Według Konwencji asynchronicznej metody nazwy w Środowisko wykonawcze systemu Windows zwykle kończy się na "Asynchronicznego".
Dodaj następujący kod w wygenerowanym pliku źródłowym C++ (w tym przykładzie zmienia nazwę Class1.cpp na Primes.cpp).is_prime Funkcji określa, czy jego danych wejściowych jest głównego.Implementuje metody pozostałe Primes klasy.Każde wywołanie create_async używa podpisu, który jest zgodny z metodą, z którego jest wywoływana.Na przykład ponieważ Primes::ComputePrimesAsync zwraca IAsyncAction, funkcja pracy, który został dostarczony do create_async nie zwraca wartości i nie przyjmuje progress_reporter obiektu jako jego 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żda metoda najpierw sprawdza poprawność do upewnij się, że to nieujemna parametrów wejściowych.Jeśli wartość wejściowa jest wartością ujemną, metoda wygeneruje Platform::InvalidArgumentException.Później tłumaczy obsługi błędów w tej sekcji.
Użycie tych metod z Windows Store aplikacji, użyj Visual C# puste aplikacji (XAML) szablon, aby dodać drugi projekt do rozwiązania Visual Studio.W tym przykładzie nazwy projektu zapory.Następnie, z zapory projekt, Dodaj odwołanie do PrimesLibrary projektu.
Dodaj następujący kod do MainPage.xaml.Ten kod definiuje interfejs użytkownika, aby 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, aby MainPage klasy w MainPage.xaml.Ten kod zawiera definicję Primes obiektu i przycisk obsługi zdarzeń.
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.Informacji o wzorców asynchronicznych, które są dostępne dla języka C# i Visual Basic, zobacz wzorców asynchronicznych w aplikacjach Sklepu Windows w języku C# i wzorców asynchronicznych w aplikacji ze Sklepu Windows z VB.
getPrimesCancellation i cancelGetPrimes metody pracować razem, Włącz użytkownika anulować operację.Jeśli użytkownik zdecyduje się na Anuluj przycisk, cancelGetPrimes wywołania metody IAsyncOperationWithProgress < TResult, TProgress >:: Anuluj Aby anulować operację.Środowisko wykonawcze współbieżności, która zarządza źródłowego operację asynchroniczną, zgłasza wyjątek typu wyjątek wewnętrzny, który jest objęte Środowisko wykonawcze systemu Windows do komunikacji wykonano anulowania.Aby uzyskać więcej informacji na temat modelu anulowania, zobacz Anulowanie w PPL.
Ważne |
---|
Aby włączyć środowisko uruchomieniowe współbieżności poprawnie zgłosić do Środowisko wykonawcze systemu Windows Aby anulował operację, nie przechwytywać tego typu wyjątek wewnętrzny.Oznacza to, że użytkownik ma również nie przechwytywać wszystkie wyjątki (catch (...)).Jeśli może przechwytywać wszystkie wyjątki, ponowne zgłoszenie wyjątku, aby upewnić się, że Środowisko wykonawcze systemu Windows można wykonać operacji anulowania. |
Na poniższej ilustracji pokazano zapory aplikacji po każdej opcji zostały wybrane.
Przykłady, które używają create_async można utworzyć zadania asynchroniczne, które mogą być używane w innych językach, zobacz za pomocą języka C++ w próbce Optymalizator podróż mapy Bing i operacji asynchronicznych systemu Windows 8 w języku C++ z PPL.
[U góry]
Kontrolowanie wątku wykonania
Środowisko wykonawcze systemu Windows Używa modelu COM, model wątków.W tym modelu obiektów znajdują się w różnych apartamenty, w zależności od tego, jak obsługują ich synchronizacji.Obiekty bezpieczeństwa wątków są obsługiwane w trybie komórek wielowątkowych (MTA).Obiekty, które muszą być dostępne za jednym wątku znajdują się w pojedynczym wątku komórkowym (Rozpocznie).
W aplikacji, która ma interfejsu użytkownika ASTA (Rozpocznie aplikacji) jest odpowiedzialny za przekazywania komunikatów okien i jest tylko wątku w procesie, który można aktualizować pracujących Rozpocznie interfejsu użytkownika.Ma to wpływ dwóch.Najpierw umożliwiające pozostanie interaktywnych aplikacji, wszystkie operacje We/Wy i intensywnie korzysta z Procesora powinien nie można uruchomić na wątku ASTA.Second wyników, które pochodzą z wątków w tle musi być przekazywane do ASTA do zaktualizowania interfejsu użytkownika.W języku C++ Windows Store aplikacji, MainPage i inne strony XAML wszystkie działają na ATSA.Dlatego continuations zadanie, które zostały zadeklarowane na ASTA są uruchamiane istnieje domyślnie, można zaktualizować formantów bezpośrednio w treści kontynuacji.Zagnieździć zadania w innym zadaniem, wszelkie continuations na zagnieżdżonej zadanie uruchamiać w trybie komórek Wielowątkowych.W związku z tym należy wziąć pod uwagę, czy jawnego określania, jakie kontekstu Uruchom te continuations.
Zadanie, które jest tworzony z operacji asynchronicznej, takich jak IAsyncOperation<TResult>, jest używana semantyki specjalnych, które mogą pomóc Ci Ignoruj szczegóły wątków.Chociaż operacji mogą być uruchamiane w wątek w tle (lub go może nie być wspierany wątku na wszystkich), jego continuations są domyślnie działanie na komórkowy, rozpoczęcia operacji kontynuacji (innymi słowy, z komórkowym, który wywołał task::then).Można użyć concurrency::task_continuation_context klasa używana do sterowania kontekstu wykonywania kontynuacji.Użyj tych metod statycznych pomocnika, aby utworzyć task_continuation_context obiektów:
Użyj concurrency::task_continuation_context::use_arbitrary do określenia, że kontynuacji działa na wątek w tle.
Użyj concurrency::task_continuation_context::use_current do określenia, czy kontynuowanie jest uruchomiony w wątku, który wywołał task::then.
Można przekazać task_continuation_context do obiektu task::then metody jawnie kontrolowania kontekstu wykonywania kontynuacji lub można przekazać zadanie do innego komórkowy, a następnie wywołać task::then metody niejawnie kontrolowania kontekstu wykonywania.
Ważne |
---|
Ponieważ głównym wątku interfejsu użytkownika Windows Store aplikacje uruchamiana Rozpocznie, continuations tworzonych w tym Rozpocznie domyślnie Uruchom na pozostaje tryb komórek jednowątkowych.W związku z tym continuations, które zostaną utworzone MTA wykonywanie MTA. |
W tej części opisano aplikację, która odczytuje plik z dysku, znajduje najbardziej popularnych wyrazów w tym pliku, a następnie wyświetla wyniki w interfejsie użytkownika.Operacja końcowa, aktualizowanie interfejsu użytkownika, występuje w wątku interfejsu użytkownika.
Ważne |
---|
To zachowanie jest charakterystyczne dla Windows Store aplikacji.W przypadku aplikacji komputerowych nie kontroli, której continuations jest uruchomiony.Zamiast tego harmonogramu wybiera wątku roboczego uruchomienia każdego kontynuacji. |
Ważne |
---|
Nie należy wywoływać metody concurrency::task::wait w treści utrzymania, które jest uruchamiane na pozostaje tryb komórek jednowątkowychW przeciwnym wypadku środowisko uruchomieniowe zgłasza wyjątek concurrency::invalid_operation, ponieważ ta metoda blokują bieżący wątek i mogą spowodować, że aplikacja przestanie odpowiadać.Jednak można wywoływać metodę concurrency::task::get w celu uzyskania wyniku zadania poprzedzającego w kontynuacji związanej z zadaniami. |
[U góry]
Przykład: Kontrolowanie wykonania w Windows Store aplikacji z języka C++ i XAML
Należy rozważyć aplikacji C++ XAML, który odczytuje plik z dysku, znajduje najbardziej popularnych wyrazów w tym pliku, a następnie wyświetla wyniki w interfejsie użytkownika.Aby utworzyć tej aplikacji, uruchom, w programie Visual Studio, tworząc Windows Store puste aplikacji (XAML) projektu i nadając mu nazwę CommonWords.W manifeście aplikacji, należy określić biblioteki dokumentów możliwości, aby umożliwić aplikacji na dostęp do folderu dokumenty.Typ pliku tekstowego (.txt) należy również dodać do sekcji deklaracji manifestu aplikacji.Aby uzyskać więcej informacji na temat możliwości aplikacji i deklaracje zobacz pakiety aplikacji i wdrażania.
Aktualizacja Grid elementu MainPage.xaml, aby uwzględnić ProgressRing elementu i TextBlock elementu.ProgressRing Oznacza, ż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 stwierdzeń, które pch.h.
#include <sstream>
#include <ppltasks.h>
#include <concurrent_unordered_map.h>
Dodaj następujące deklaracje metody do 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 stwierdzeń, które MainPage.cpp.
using namespace concurrency;
using namespace std;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
W MainPage.cpp, należy zaimplementować MainPage::MakeWordList, MainPage::FindCommonWords, i MainPage::ShowResults metody.MainPage::MakeWordList i MainPage::FindCommonWords praktyce intensywnie korzysta z operacji.MainPage::ShowResults Metoda wyświetla wyniki obliczeń 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());
}
Modyfikuj MainPage Konstruktor do tworzenia łańcucha zadania kontynuacji wyświetlany w interfejsie użytkownika popularnych wyrazów w książce Iliad przez Homer.Pierwszy zadania dwóch kontynuację, które podział tekstu na pojedyncze wyrazy i Znajdź popularnych wyrazów, może być czasochłonne i dlatego ustawiono jawnie do uruchamiania w tle.Zadanie końcowe kontynuacji aktualizuje interfejsu użytkownika, Określa kontekst nie kontynuacji i w związku z powyższym komórkowy wątki reguły.
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 przykładzie pokazano, jak określić kontekst wykonywania oraz sposób Napisz łańcucha continuations.Wycofaj, że domyślnie zadanie, które jest tworzony na podstawie operacji asynchronicznej jest uruchamiany jej continuations na komórkowy, który wywołał task::then.W tym przykładzie zastosowano task_continuation_context::use_arbitrary do określenia, czy operacje, które nie wymagają interfejsu użytkownika można wykonać na wątek w tle.
Na poniższej ilustracji pokazano wyniki CommonWords aplikacji.
W tym przykładzie jest możliwy do obsługi anulowania, ponieważ task obiektów, które obsługują create_async Użyj tokenu niejawne anulowania.Zdefiniuj swoje przez funkcję pracy cancellation_token obiektu, jeśli zadań trzeba odpowiedzieć anulowania w sposób współpracy.Aby uzyskać dodatkowe informacje na temat anulowania w PPL, zobacz Anulowanie w PPL
[U góry]