Создание асинхронных операций в C++ для приложений для Магазина Windows
В этом документе описываются некоторые узловых элементов, чтобы помнить при использовании среда выполнения с параллелизмом для создания асинхронных операций в приложении Магазина Windows.
Использование асинхронного программирования является ключевым компонентом в модели приложения Магазина Windows, поскольку позволяет приложения не реагировать на ввод пользователя.Можно запустить длительная задачи без блокировки потока пользовательского интерфейса, можно получать результаты задачи позже.Можно также задачи отмены и получение уведомлений о ходе выполнения в задачи, выполняемые в фоновом режиме.Представляет Асинхронное программирование в C, C-++ общие сведения об асинхронной модели, которая доступна в Visual C-++ C - создание приложения Магазина Windows.Этот документ описывает, как и к потреблению и создает цепочки асинхронных операций в Среда выполнения Windows.В этом разделе описывается, как использовать среду выполнения с параллелизмом для создания асинхронных операций, которые могут быть использованы другим компонентом Среда выполнения Windows и как к элементу управления как асинхронный рабочий выполняется.Также рекомендуется прочитать Async программирования шаблоны и советы в Hilo (Магазина приложения Windows с помощью C и C-++ XAML), чтобы понять, как следует использовать среду выполнения с параллелизмом для реализации асинхронных операций в Hilo, приложение Магазина Windows с помощью C и C-++ XAML.
Примечание |
---|
Можно использовать Библиотека параллельных шаблонов и Библиотека асинхронных агентов в приложении Магазина Windows.Однако нельзя использовать планировщик заданий или диспетчер ресурсов.В этом документе описываются дополнительные функции, среда выполнения с параллелизмом предоставляет только вошедшим в приложение Магазина Windows, а не классическое приложение. |
Ключевые моменты
Используйте concurrency::create_async для создания асинхронных операций, которые могут использоваться другими компонентами (которые могут быть записаны в языках, отличных от C ++).
Используйте concurrency::progress_reporter, чтобы сообщить о ходе выполнения на компоненты, которые вызывают для асинхронных операций.
Используйте токены отмены, чтобы позволить внутренние асинхронные операции отмены.
Расширение функциональности функции create_async зависит от возвращаемом типе рабочей функции, передаваемой в нее.Рабочая функция, возвращающая выполнения задачи ( task<T> или task<void>) одновременно в контексте, который вызвал метод create_async.Рабочая функция, которая возвращает T или void выполняется в произвольном контексте.
Можно использовать метод concurrency::task::then для создания цепочки задач, выполняемых один за другим.В приложении Магазина Windows, контекст по умолчанию для продолжения задачи зависит от способа, для формирования.Если задача была создана путем передачи асинхронного действия в конструктор задачи, или путем передачи лямбда-выражение, возвращающее асинхронного действия, то контекст по умолчанию для всех по этой задачи текущего контекста.Если задача не выполняется после асинхронного действия, произвольный контекст используется по умолчанию для продолжения задачи.Можно переопределить контекст по умолчанию с помощью класса concurrency::task_continuation_context.
В этом документе имеются следующие главы:
Создание асинхронных операций
Пример: Чтобы создать компонент времени выполнения Windows A C на C-++.
Управление потоком выполнения
Пример: Управление выполнением Магазина в приложение Windows с C и C-++ XAML
Создание асинхронных операций
Для этого можно использовать и модель продолжения (PPL) в библиотеке параллельных шаблонов определить фоновых задач, так и дополнительные задачи, выполняемые при предыдущая задача завершается.Эта функция предоставляется классом concurrency::task.Дополнительные сведения об этой модели и классе task см. в разделе Параллелизм задач (среда выполнения с параллелизмом).
Среда выполнения Windows - это программный интерфейс, который можно использовать для создания приложений Магазина Windows, которые запускаются в специальную среде операционной системы.Такие функции, типы данных и устройства приложений авторизованные использованием и добавленное в Магазин Windows.Среда выполнения Windows предоставляет интерфейс для приложений интерфейсом приложений двоичным (ABI).ABI основной бинарный контракт, который предоставляет API Среда выполнения Windows доступными для языков программирования, например Visual C C-++.
С помощью Среда выполнения Windows можно использовать лучшие функции различных языков программирования и объедините их в одно приложение.Например, можно создать пользовательский интерфейс в JavaScript и запуск ресурсоемкая логика приложения в компоненте A.C на C-++.Возможность выполнять такие ресурсоемкие операции в фоновом режиме является ключевым фактором в обеспечить пользовательский интерфейс интерактивного.Поскольку класс task используется в C, C-++, необходимо использовать интерфейс Среда выполнения Windows взаимодействовать асинхронных операций другим компонентам (которые могут быть записаны в языках, отличных от C ++).Среда выполнения Windows предоставляет 4 интерфейса, который можно использовать для представления асинхронных операций:
Windows::Foundation::IAsyncAction
Представляет асинхронного действия.Windows::Foundation::IAsyncActionWithProgress<TProgress>
Представляет асинхронного действия, отчеты ".Windows::Foundation::IAsyncOperation<TResult>
Представляет асинхронную операцию, которая возвращает результат.Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>
Представляет асинхронную операцию, которая возвращает результат и отчетов ".
Принцип действия означает, что асинхронная задача не создает значение функции, возвращающей (класс void).Понятие операции означает, что асинхронная задача создает значение.Понятие хода выполнения означает, что задача может получить сообщение о ходе выполнения в вызывающий объект.JavaScript, .NET Framework, а Visual C-++ C каждое предоставляют собственным способом создания экземпляров этих интерфейсов для использования через границы ABI.Для Visual C#, C-++, среда выполнения с параллелизмом предоставляет функцию concurrency::create_async.Эта функция создает действие или асинхронные операции Среда выполнения Windows, представляющих завершения задачи.Функция create_async принимает рабочую функцию (обычно лямбда-выражение), внутренне создается объект task и использование оболочки, задачу в одном из 4 асинхронных интерфейсов Среда выполнения Windows.
Примечание |
---|
Используйте create_async только при необходимости создать функцию, можно получить из другого языка или других компонентов Среда выполнения Windows.Используйте класс task напрямую, если известно, что операция и создается и используется C кодом C-++ в одном компоненте. |
Возвращаемый тип определяется типом create_async аргументов.Например, если ваша рабочая функция не возвращает значение и не сообщает о ходе выполнения, то create_async возвращает IAsyncAction.Если ваша рабочая функция не возвращает значение и также отчетов ", то create_async возвращает IAsyncActionWithProgress.Сообщает о ходе выполнения, укажите объект concurrency::progress_reporter в качестве параметра в рабочей функции.Возможность уведомить ход выполнения позволяет сообщить объем работы, выполненной и какой объем, остается (например, как процент).Она также позволяет получить результаты, как только они становятся доступными.
IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult> и IAsyncActionOperationWithProgress<TProgress, TProgress> предоставляют интерфейсы каждый метод Cancel, который позволяет отменить асинхронной операции.Класс task работает с помощью токенов отмены;При использовании токен отмены, чтобы отменить работу, среда выполнения не запускается новая работа с соблюдением на этот токен.Работа, уже активно может отслеживать его токен отмены и остановки, когда он может.Этот механизм описана подробнее в документе Отмена в библиотеке параллельных шаблонов.Можно подключиться отмена задач с использованием Среда выполнения WindowsCancel в 2 вариантах.Во-первых, можно указать рабочую функцию, которую необходимо передать значение create_async, чтобы получить объект concurrency::cancellation_token.При вызове метода Cancel, этот токен отмены его отмены и обычные правила применяются к основной объект task, поддерживающий вызов create_async.Если не предоставить объект cancellation_token, соответствующий объект task определяет одно неявно.Определите объект cancellation_token при необходимости совместно реагировать на отмену в вашей рабочей функции.Пример Пример: Управление выполнением Магазина в приложение Windows с C и C-++ XAML раздела показано, как выполнить отмену в приложении Магазина Windows с помощью C-# и XAML, использующего пользовательский компонент C к Среда выполнения Windows.
Внимание |
---|
В цепочке продолжений задач, всегда очистка состояние, а затем вызвать метод concurrency::cancel_current_task при concurrency::is_task_cancellation_requested возвращает значение true.Если возврат ранее вместо вызова метода cancel_current_task, то операция переходит в состояние завершения вместо отмененного состояния. |
В следующей таблице приведены сочетания, которые можно использовать для задания асинхронных операций в приложении.
Создать этот интерфейс Среда выполнения Windows |
Возвращает этот тип из create_async |
Передайте эти типы параметров в рабочей функции для использования неявного токена отмены |
Передайте эти типы параметров в рабочей функции для использования явного токена отмены |
---|---|---|---|
IAsyncAction |
void или task<void> |
(нет) |
(cancellation_token) |
IAsyncActionWithProgress<TProgress> |
void или task<void> |
(progress_reporter) |
(progress_reporter, cancellation_token) |
IAsyncOperation<TResult> |
T или task<T> |
(нет) |
(cancellation_token) |
IAsyncActionOperationWithProgress<TProgress, TProgress> |
T или task<T> |
(progress_reporter) |
(progress_reporter, cancellation_token) |
Можно вернуть значение или объект task из рабочей функции, указанное в функции create_async.Эти различия создают различные расширения функциональности.Если возвращается значение, рабочая функция создана программу-оболочку в task, чтобы ее можно выполнить в фоновом потоке.Кроме того, основные task используется неявное токена отмены.И наоборот, если возвращается объект task, рабочая функция выполняется одновременно.Следовательно, если возвращается объект task убедитесь, что все длинномерные операции в вашей рабочей функции выполняются как задачи, чтобы приложение не отзывчивыми.Кроме того, основные task не использует неявный токена отмены.Поэтому необходимо определить вашу рабочую функцию, которая принимает объект cancellation_token, если необходима поддержка отмены, если возвращается объект task из коллекции create_async.
В следующем примере показаны различные способы создания объекта IAsyncAction, который может быть использован другим компонентом Среда выполнения Windows.
// 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.
});
});
[Верх]
Пример: Чтобы создать компонент времени выполнения Windows и использовать A.C, C-++, C#.
Рассмотрим приложение, которое использует XAML и C-# для определения пользовательского интерфейса и компонент а. C на C-++ Среда выполнения Windows для выполнения compute-, операции.В этом примере компонент C, C-++, вычисляет числа в заданном диапазоне основные.Чтобы увидеть различия между 4 интерфейсов асинхронных задач Среда выполнения Windows, start, в Visual Studio, путем создания Новое решение и назовите его Воспламеняет.Затем добавьте в решение проект Компонент среды выполнения Windows и назовите его PrimesLibrary.Добавьте следующий код в создаваемый файл заголовка C C-++ (этот пример переименовывает Class1.h в Primes.h).Каждый метод public определяет один из 4 асинхронных интерфейсов.Методы, возвращающие вернуть Windows::Foundation::Collections::IVector<int> значение объекта.Методы, которые уведомляют ход выполнения создают значений double, указывающих доля общего работы, завершена.
#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);
};
}
Примечание |
---|
По соглашению асинхронные имена методов в Среда выполнения Windows обычно заканчивается Async. |
Добавьте следующий код в создаваемый файл источника C C-++ (этот пример переименовывает Class1.cpp в Primes.cpp).Функция is_prime определяет, является ли его основные данные.Остальные методы реализуют класс Primes.Каждый вызов create_async использует сигнатуру, совместимой с методом, из которого он вызывается.Например, поскольку Primes::ComputePrimesAsync возвращает IAsyncAction, рабочей функции, реализуемый create_async не возвращает значение и не принимает объект progress_reporter в качестве параметра.
// 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;
});
}
Каждый метод сначала выполняет проверку, чтобы убедиться, что входные параметры не являются отрицательными.Если входное значение отрицательное, метод Platform::InvalidArgumentException создает исключение.Обработка ошибок объясняется далее в этом разделе.
Чтобы использовать эти методы из приложения Магазина Windows, используйте шаблон Visual C# Пустое приложение (XAML), чтобы добавить второй проект в решение Visual Studio.Имена этого примера проект Воспламеняет.Затем, из проекта Воспламеняет добавьте ссылку на проект PrimesLibrary.
Добавьте следующий код в MainPage.xaml.Этот код определяет пользовательский интерфейс, чтобы можно было вызвать результаты компонента отображения C и C-++.
<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>
Добавьте следующий код в класс MainPage в MainPage.xaml.Этот код определяет объект Primes и обработчики событий для кнопки.
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();
}
Эти методы используются ключевые слова async и await для обновления пользовательского интерфейса после выполнения асинхронных операций.Дополнительные сведения об асинхронных моделях, доступных для C-# и Visual Basic см. в Асинхронные модели в приложениях Windows с помощью C-# Магазина разделе и Асинхронные модели в приложениях Windows с VB Магазина.
Методы getPrimesCancellation и cancelGetPrimes работают вместе, чтобы позволить пользователю отменить операцию.Когда пользователь выбирает кнопка Отмена, вызывает IAsyncOperationWithProgress<TResult, TProgress>::Cancel метод cancelGetPrimes для отмены операции.Среда выполнения с параллелизмом, которая управляет основной асинхронной операции, создает внутренний тип исключения, которое уловлен Среда выполнения Windows для взаимодействия, что отмена завершена.Дополнительные сведения о модели отмены см. в разделе Отмена в библиотеке параллельных шаблонов.
Важно |
---|
Чтобы включить среда выполнения с параллелизмом правильно уведомления в Среда выполнения Windows, он отменила операция, не перехватывайте этот внутренний тип исключения.Это означает, что не следует также перехват всех исключений (catch (...)).Если необходимо перехват всех исключений, повторно создавать исключение, чтобы убедиться, что Среда выполнения Windows может выполнить операцию отмены. |
На следующем рисунке показано приложение Воспламеняет после каждого параметра был выбран.
Примеры используют метод create_async для создания асинхронных задач, которые могут использоваться другими языками, см. Использование C C-++ в примере оптимизатора отключения карт Bing и Асинхронные операции в Windows 8 C C-++ с PPL.
[Верх]
Управление потоком выполнения
Среда выполнения Windows использует потоковую модель COM.В этой модели объектов, размещенных в различных подразделениях, в зависимости от того, как они обрабатывают их синхронизации.Потокобезопасные объекты размещаются в нескольких потоков для подразделении (MTA).Объекты, которые должны быть доступны для одним потоком размещаются в однопотоковом подразделении (STA).
В приложении, в котором имеется пользовательский интерфейс, поток ASTA приложения (STA) отвечает за накачка сообщения окна и один поток в процессе, который может обновить STA- размещенные элементы управления пользовательского интерфейса.Это имеет 2 последствиям.Сначала необходимо включить в приложение отзывчивыми, все операции этот интенсивных и ВВОДА-ВЫВОДА не должны выполняться в потоке ASTA.Во-вторых, результаты, полученные из фоновых потоков, маршалировались обратно в ASTA для обновления пользовательский интерфейс.В приложении A.C, C-++, Магазина WindowsMainPage и других страницах XAML все выполнение в ATSA.Поэтому продолжения задачи, объявляются в ASTA выполняются там по умолчанию, поэтому следует управления обновления напрямую в теле продолжения.Однако если поместите задачу в другой задаче, все продолжения в этой вложенной задачи выполняются в многопотоковом подразделении.Поэтому необходимо рассмотреть, необходимо ли явно указать в каком контексте выполнения этих продолжений.
Задача, которая создается из асинхронной операции, такие как IAsyncOperation<TResult>, использует специальную семантику, которые помогут игнорировать передавая накапливаемое значение сведения.Хотя операция может выполняться в фоновом потоке (или база данных не может быть обеспечивается потоком вообще), гарантируется выполнение его продолжения по умолчанию в подразделении, начавшего операции продолжения (другими словами, из контейнера, которое вызвало task::then).Можно использовать класс concurrency::task_continuation_context в элемент управления контекст выполнения продолжения.Эти вспомогательные статические методы для создания объектов task_continuation_context.
Используйте concurrency::task_continuation_context::use_arbitrary, чтобы указать, что продолжение выполняется в фоновом потоке.
Используйте concurrency::task_continuation_context::use_current, чтобы указать, что продолжение выполняется для потока, который вызвал метод task::then.
Можно передать объект task_continuation_context методу task::then явно элемент управления контекст выполнения продолжения или можно передать задачу в другой подразделение и затем вызовите метод task::then неявно к элементу управления контекстом выполнения.
Важно |
---|
Поскольку основной поток пользовательского интерфейса приложений Магазина Windows выполняется в режиме STA, продолжения, созданных на этом STA по умолчанию выполняются на однопотоковое подразделение.Соответственно, продолжения, созданные в многопотоковом подразделении выполняемых в многопотоковом подразделении. |
В следующем разделе показано приложение, считывающее файл с диска, найти наиболее общеупотребительные ключевые слова в этом файле, а затем отображает результаты в пользовательском интерфейсе.Последняя операция, при обновлении пользовательского интерфейса, происходит в потоке пользовательского интерфейса.
Важно |
---|
Это расширение функциональности относятся к приложениям Магазина Windows.Для классических приложений не требуется элемент управления, запустите продолжений.Вместо этого планировщик выбирает рабочего потока, в котором требуется выполнить каждое продолжения. |
Важно |
---|
Не вызывайте concurrency::task::wait в теле продолжения выполняемого на однопотоковое подразделение.В противном случае среда выполнения создает исключение concurrency::invalid_operation, поскольку этот метод блокирует текущий поток и может привести к его к безответным.Однако можно вызвать метод concurrency::task::get, чтобы получить результат предшествующей задачи в соответствии с задачами продолжении. |
[Верх]
Пример: Управление выполнения в приложении Магазина Windows с C и C-++ XAML
Рассмотрим приложение A.C на C-++ XAML, считывает файл с диска, найти наиболее общеупотребительные ключевые слова в этом файле, а затем отображает результаты в пользовательском интерфейсе.Чтобы создать приложение, start, в Visual Studio, необходимо создать проект Магазина WindowsПустое приложение (XAML) и назовите его CommonWords.В манифесте приложения укажите возможность Библиотека документов позволяет приложению обращаться к папке.Добавить тип файла текста (TXT) в раздел объявлений манифеста приложения.Дополнительные сведения о возможностях и объявлениях приложения см. в разделе Пакеты и развертывание приложения.
Обновление элемента Grid в MainPage.xaml для включения элемента ProgressRing и элемент TextBlock.ProgressRing указывает, что операция выполняется TextBlock и отображает результаты вычислений.
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ProgressRing x:Name="Progress"/>
<TextBlock x:Name="Results" FontSize="16"/>
</Grid>
Добавьте следующие выписки #include в pch.h.
#include <sstream>
#include <ppltasks.h>
#include <concurrent_unordered_map.h>
Добавьте следующие объявления приема в класс MainPage (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);
Добавьте следующие выписки using в MainPage.cpp.
using namespace concurrency;
using namespace std;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
В MainPage.cpp, реализуйте интерфейс MainPage::MakeWordList, методы MainPage::FindCommonWords и MainPage::ShowResults.MainPage::MakeWordList и MainPage::FindCommonWords выполняют ресурсоемкие операции.Метод MainPage::ShowResults показывает результат вычисления в пользовательском интерфейсе.
// 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());
}
Измените конструктор MainPage для создания цепочки задач продолжения тех, которые будут отображаться в пользовательском интерфейсе общеупотребительные ключевые слова в книге Илиада почтовым голубем.Первые 2 задач продолжения, которая разделят текст на отдельные слова и найти общеупотребительные ключевые слова, может занимать продолжительное время, поэтому явно задать для выполнения в фоновом режиме.Последняя задача продолжения, которая обновляет пользовательский интерфейс, не определяет никакие контекст продолжения, поэтому удовлетворяет правилам потоковую модель " Подразделение ".
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.
});
}
Примечание |
---|
В этом примере показано, как определить контексты выполнения и как составление цепочку продолжений.Помните, что по умолчанию задача, созданная из асинхронной операции выполняется его продолжения в подразделении, вызывает task::then.Таким образом, в этом примере используется task_continuation_context::use_arbitrary для указания того, что операции, которые не имеют пользовательского интерфейса реализованы в фоновом потоке. |
На следующем рисунке показаны результаты выполнения приложения CommonWords.
В этом примере, можно поддерживать отмену, поскольку объекты task, поддерживают использование create_async неявный токена отмены.Определить вашу рабочую функцию, которая принимает объект cancellation_token, если к задачам должен ответить на отмену в, чтобы способом.Дополнительные сведения об отмене в PPL см. в разделе Отмена в библиотеке параллельных шаблонов.
[Верх]