C++로 Windows 스토어 앱용 비동기 작업 만들기
이 문서의 동시성 런타임을 사용 하 여 비동기 작업에서 생성 하는 경우에 기억해 야 할 주요 사항 중 일부에 대해 설명 된 Windows 스토어 응용 프로그램입니다.
비동기 프로그래밍의 사용의 핵심 구성 요소입니다의 Windows 스토어 응용 프로그램이 사용자 입력에 응답을 유지할 수 있도록 하기 때문에 응용 프로그램을 모델링 합니다.UI 스레드를 차단 하지 않고 장기 실행 작업을 시작할 수 및 작업을 나중에 결과를 받을 수 있습니다.작업을 취소 하 고 백그라운드에서 실행 되는 작업 진행률 알림의 받을 수도 있습니다.문서 c + +에서는 비동기 프로그래밍 만들려면 Visual C++ 사용할 수 있는 비동기 패턴에 대 한 개요를 제공 Windows 스토어 응용 프로그램입니다.해당 문서 체인 비동기 작업을 만들고 사용 하는 방법에 설명 Windows 런타임 작업 합니다.이 단원에서는 동시성 런타임에서 다른 사용할 수 있는 비동기 작업을 만들기 위해 사용 하는 방법을 설명 Windows 런타임 는 비동기 작업을 제어 하는 방법 및 구성 요소를 실행 합니다.또한 읽는 것이 좋습니다 비동기 프로그래밍 패턴 및 팁 고 저 형 (c + + 및 XAML을 사용 하 여 Windows 저장소 응용 프로그램)에 어떻게 우리가 동시성 런타임은 비동기 작업 고 저 형에서 구현 하는 데에 Windows 스토어 c + + 및 XAML을 사용 하 여 응용 프로그램.
[!참고]
사용 하면은 병렬 패턴 라이브러리 (PPL) 및 비동기 에이전트 라이브러리 에 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 클래스입니다.
이 문서에서 다루는 내용
비동기 작업 만들기
예: c + + Windows 런타임 구성 요소 만들기
실행 스레드를 제어합니다.
XAML 및 c + +는 Windows 저장소 응용 프로그램의 실행을 제어 하는 예:
비동기 작업 만들기
백그라운드 작업은 물론 이전 작업이 완료 될 때 실행 되는 추가 작업을 정의 하는 PPL (병렬 패턴 라이브러리에서) 작업 및 연속 작업 모델을 사용할 수 있습니다.이 기능을 제공 하는 concurrency::task 클래스입니다.이 모델에 대 한 자세한 내용은 및 task 클래스를 참조 하십시오 작업 병렬 처리(동시성 런타임).
Windows 런타임 를 만드는 데 사용할 수 있는 프로그래밍 인터페이스입니다 Windows 스토어 만 특별 한 운영 체제 환경에서 실행 되는 응용 프로그램입니다.이러한 응용 프로그램 권한이 부여 된 함수, 데이터 형식 및 장치를 사용 하 여 및에서 배포 되는 Windows 스토어.Windows 런타임 표시 되는 응용 프로그램 이진 인터페이스 (ABI).하는 기본 이진 계약 된 ABI는 Windows 런타임 Visual C++ 같은 프로그래밍 언어에 사용할 수 있는 Api입니다.
사용 하는 Windows 런타임, 다양 한 프로그래밍 언어의 최상의 기능을 사용 하 고 결합 하 여 하나의 응용 프로그램에 있습니다.예를 들어, Javascript에서 UI를 만드는 하 고 c + + 구성 요소에 계산을 많이 응용 프로그램 논리를 수행할 수 있습니다.이러한 계산을 많이 작업을 백그라운드에서 수행할 수 있는 응답성이 뛰어난 UI를 유지 하는 중요 한 요소입니다.때문에 task 클래스는 c + +를 사용 해야는 Windows 런타임 (c + + 이외의 언어로 작성할 수 있습니다) 다른 구성에 대 한 비동기 작업과 통신 하는 인터페이스.Windows 런타임 비동기 작업을 나타내는 데 사용할 수 있는 네 개의 인터페이스를 제공 합니다.
Windows::Foundation::IAsyncAction
비동기 동작을 나타냅니다.Windows::Foundation::IAsyncActionWithProgress <TProgress>
진행률을 보고 하는 비동기 작업을 나타냅니다.Windows::Foundation::IAsyncOperation <TResult>
결과 반환 하는 비동기 작업을 나타냅니다.< TResult, TProgress > Windows::Foundation::IAsyncOperationWithProgress
진행 결과 보고서를 반환 하는 비동기 작업을 나타냅니다.
개념은 작업 비동기 작업의 값을 생성 하지 않는 것을 의미 (인지 반환 하는 함수를 void).개념은 작업 비동기 작업 값을 산출 하지 의미 합니다.개념 진행 중인 작업 진행률 메시지를 호출자에 게 보고할 수 있도록 하는 것을 의미 합니다.JavaScript,.NET Framework, 및 각 Visual C++ ABI 경계를 넘어 사용 하기 위해이 인터페이스의 인스턴스를 만들 수 자체를 제공 합니다.동시성 런타임은 Visual C++ 제공 된 concurrency::create_async 함수.이 함수를 만듭니다는 Windows 런타임 비동기 작업 또는 작업의 완료를 나타내는 작업입니다.create_async 함수 작업 함수 (람다 식 일반적으로) 사용, 내부적으로 생성은 task 개체와 네 개의 비동기 중 하나에서 작업 하는 래핑 Windows 런타임 인터페이스.
[!참고]
사용 create_async 다른 언어 또는 다른 폴더에서 액세스할 수 있는 기능을 만들 수 있을 때만 Windows 런타임 구성 요소입니다.사용 된 task 작업이 모두 생성 이며 c + + 코드를 같은 구성 요소에 의해 사용 되는 알고 직접 클래스입니다.
반환 형식에 create_async 는 형식 인수에 의해 결정 됩니다.예를 들어, 값을 반환 하지 않는 작업 함수를 사용 하 여 진행률을 보고 하지 않습니다 경우 create_async 반환 IAsyncAction.작업 함수를 사용 하 여 값을 반환 하지 않는 및 또한 진행 상황을 보고 하는 경우 create_async 반환 IAsyncActionWithProgress.진행률 보고를 제공 하는 concurrency::progress_reporter 작업 함수를 매개 변수로 개체입니다.진행률을 보고 하는 기능이 어떤 양의 작업을 수행 하지 및 금액 (예를 들어, 백분율) 남아 보고할 수 있습니다.또한 결과를 보고 있을 때 있습니다.
IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, 및 IAsyncActionOperationWithProgress<TProgress, TProgress> 각 인터페이스 제공은 Cancel 메서드는 비동기 작업을 취소할 수 있습니다.task 클래스에 취소 토큰을 작동 합니다.취소 토큰을 사용 하 여 작업을 취소 하는 경우 런타임에서 해당 토큰을 구독 하는 새 작업을 시작 하지 않습니다.이미 활성화 된 작업은 취소 토큰을 모니터링 하 고 중지 수 있습니다.이 메커니즘은 문서에서 자세히 설명 되어 PPL에서의 취소.작업 취소와 연결할 수 있는 Windows 런타임Cancel 메서드를 두 가지 방법으로. 먼저 전달 하는 작업 함수를 정의할 수 있습니다 create_async 수행 하는 concurrency::cancellation_token 개체입니다.때의 Cancel 메서드가 호출 되 고,이 취소 토큰이 취소 된 내부에 적용 되는 일반 취소 규칙 task 지 원하는 개체는 create_async 호출 합니다.제공 하지 않는 경우는 cancellation_token 개체의 내부 task 개체 정의 하나 암시적입니다.정의 cancellation_token 개체 협조적 취소 작업 함수에 응답 하는 경우.섹션 예제: XAML 및 c + +는 Windows 저장소 응용 프로그램의 실행을 제어 에서 취소를 수행 하는 방법의 예를 나타낸는 Windows 스토어 C# 및 사용자 지정을 사용 하 여 XAML 응용 프로그램 Windows 런타임 c + + 구성 요소.
주의 |
---|
작업 연속 체인, 항상 상태를 정리 하 고 호출 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.
});
});
Top
예: c + + Windows 런타임 구성 요소 만들기 및 C# 사용
XAML 및 C#를 사용 하 여 c + + 및 UI를 정의 하는 응용 프로그램 고려 Windows 런타임 연산 집약적인 작업을 수행 하는 구성 요소입니다.이 예제에서는 소수 지정 된 범위에 있는 숫자는 c + + 구성 요소를 계산 합니다.네 간의 차이점을 보여 주기 위해 Windows 런타임 인터페이스 비동기 작업을 시작, Visual Studio 생성 하 여는 빈 솔루션 이름을 지정 하 고 프라임.다음 솔루션에 추가 된 Windows 런타임 구성 요소 프로젝트 이름을 지정 하 고 PrimesLibrary.(이 예제에서는 class1.h에 Primes.h 이름을 바꿉니다) 생성 된 c + + 헤더 파일에 다음 코드를 추가 합니다.각 public 메서드를 정의 하는 네 개의 비동기 인터페이스 중 하나입니다.반환 값을 반환 하는 메서드는 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 + + 소스 파일 (이 예제에서는 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;
});
}
먼저 각 메서드 입력된 매개 변수는 음수가 되는지 확인 하는 유효성 검사를 수행 합니다.입력된 값이 음수인 경우 throw Platform::InvalidArgumentException.오류 처리에 나중에이 섹션에 설명 되어 있습니다.
이러한 메서드를 사용 하는 Windows 스토어 응용 프로그램을 사용할 Visual C# 빈 응용 프로그램 (XAML) 두 번째 프로젝트는 Visual Studio 솔루션에 추가 하려면 서식 파일.이 예제에서는 프로젝트의 이름을 프라임.다음에서 프라임 프로젝트에 대 한 참조를 추가 PrimesLibrary 프로젝트입니다.
Mainpage.xaml에 다음 코드를 추가 합니다.이 코드가 c + + 구성 요소를 호출 하 고 결과 표시할 수 있도록 UI를 정의 합니다.
<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 비동기 작업을 완료 한 후에 UI를 업데이트 하는 키워드입니다.C# 및 Visual Basic 사용할 수 있는 비동기 패턴에 대 한 내용은 C#와 Windows 저장소 응용 프로그램에서 비동기 패턴 및 Windows 저장소 VB 응용 프로그램에서 비동기 패턴.
getPrimesCancellation 및 cancelGetPrimes 메서드가 함께 작동 사용자가 작업을 취소할 수 있도록 합니다.사용자를 선택 하면는 취소 단추는 cancelGetPrimes 메서드 호출 IAsyncOperationWithProgress < TResult, TProgress >:: 취소 작업을 취소 하려면.내부 예외 형식을 catch 되어 내부 비동기 작업을 관리 하는 동시성 런타임에서 throw 된 Windows 런타임 취소 완료 통신을.취소 모델에 대 한 자세한 내용은 PPL에서의 취소.
중요 |
---|
동시성 런타임에서 정확 하 게 보고할 수 있도록의 Windows 런타임 해당 작업이 취소 되었습니다,이 내부 예외 형식을 catch 하지 않습니다.또한 모든 catch 해야 않는 것 즉, 예외 (catch (...)).모든 catch 해야 하는 경우 예외를 다시 throw 하는 예외는 Windows 런타임 취소 작업을 완료할 수 있습니다. |
다음 그림은 프라임 각 옵션을 선택 하면 응용 프로그램.
사용 예 create_async 기타 언어에서 사용할 수 있는 비동기 작업을 작성 하려면를 참조 하십시오 를 사용 하 여 Bing 지도 여행 최적기 샘플에서 c + + 및 PPL c + +에서 Windows 8 비동기 작업.
Top
실행 스레드를 제어합니다.
Windows 런타임 COM 스레딩 모델을 사용 합니다.이 모델에서는 개체의 동기화 처리 하는 방법에 따라 서로 다른 아파트에서 호스팅됩니다.스레드로부터 안전한 개체에는 다중 스레드 아파트 (MTA)에서 호스팅됩니다.단일 스레드를 통한 액세스 해야 하는 개체 (STA)는 단일 스레드 아파트에서 호스팅됩니다.
UI를 가진 응용 프로그램을 ASTA (응용 프로그램이 STA) 스레드 창 메시지 펌프에 대 한 역할을 담당 하 고 유일한 스레드 STA 호스트는 UI 컨트롤을 업데이트할 수 있는 프로세스에서입니다.이 두 가지 결과가 발생 합니다.첫째, 응용 프로그램에서 응답을 유지할 수 있도록 모든 CPU와 I/O 작업 ASTA 스레드에서 실행할 수 합니다.둘째, 배경 스레드에서 오는 결과 UI를 업데이트 하는 ASTA에 다시 마샬링되어야 합니다.C + +에서 Windows 스토어 응용 프로그램 MainPage ATSA에서 다른 모든 XAML 페이지를 실행 합니다.따라서 연속 본문에서 직접 컨트롤을 업데이트할 수 있도록 ASTA에 선언 된 작업 연속도 기본적으로 실행 됩니다.그러나 작업에서 다른 작업을 중첩 한 경우 모든 중첩 된 작업의 연속에서 MTA를 실행 합니다.따라서 고려해 야 어떤 컨텍스트에서 이러한 연속 실행을 명시적으로 지정 해야 합니다.
비동기 작업에서 만들어진 경우 작업 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 메서드가 암시적으로 실행 컨텍스트를 제어할 수.
중요 |
---|
때문에 주 UI 스레드를 Windows 스토어 응용 프로그램에서 STA 실행, 기본적으로 해당 STA에 만든 연속 실행에 STA.따라서 MTA에서 만들 연속 MTA에서 실행 됩니다. |
다음 단원에서는 디스크에서 파일을 읽고, 가장 일반적인 단어에 해당 파일을 찾습니다 및 다음 UI에 결과 표시 하는 응용 프로그램을 보여 줍니다.UI를 업데이트 하는 마지막 작업을 UI 스레드에서 발생 합니다.
중요 |
---|
이 문제는 관련 된 Windows 스토어 응용 프로그램입니다.데스크톱 응용 프로그램의 경우 연속 작업을 실행 하는 제어 하지 않습니다.대신, 각 연속 작업이 실행 하는 작업자 스레드 스케줄러를 선택 합니다. |
중요 |
---|
호출 하지 마십시오 concurrency::task::wait STA.에서 실행 되는 연속 작업의 본문에그렇지 않으면 런타임에서 throw concurrency::invalid_operation 때문에이 메서드는 현재 스레드를 차단 하 고 응용 프로그램에서 응답 하지 않을 발생할 수 있습니다.호출할 수 있는 concurrency::task::get 작업 기반 연속 작업에 선행 작업의 결과 받는 방법. |
Top
예: 실행을 제어 하는 Windows 스토어 된 XAML 및 c + + 응용 프로그램
디스크에서 파일을 읽고, 가장 일반적인 단어에 해당 파일을 찾습니다 및 다음 UI에 결과 표시 하는 XAML c + + 응용 프로그램을 고려해 야 합니다.이 응용 프로그램을 만들려면 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 메서드 계산의 결과 UI에 표시 합니다.
// 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 일반적인 단어 책의 UI에 표시 체인의 연속 작업을 만들 수 있는 생성자 의 Iliad Homer가.텍스트가 개별 단어로 분할 하 고 일반적인 단어 찾기, 첫 번째 두 개의 연속 작업 시간이 많이 걸릴 수 및 따라서 백그라운드에서 실행 되도록 명시적으로 설정 합니다.UI를 업데이트 하는 마지막 연속 작업 없는 연속 컨텍스트를 지정 하 고 따라서 아파트 스레딩 규칙을 따릅니다.
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 UI와 관련이 없는 작업은 백그라운드 스레드에서 수행 하는 것을 지정 합니다.
결과를 다음 그림과 CommonWords 응용 프로그램입니다.
이 예제에서는 취소 기능을 지원 하기 때문에 가능한 것은 task 개체를 지 원하는 create_async 는 암시적 취소 토큰을 사용 합니다.작업에 함수가 정의 된 cancellation_token 개체 작업 취소는 협조적 방식으로 응답 해야 하는지.PPL에서 취소 하는 방법에 대 한 자세한 정보를 참조 하십시오.PPL에서의 취소
Top