Instruktaż: Wykonawczych prognoz
W tym temacie przedstawiono sposób wykonania prognoz w aplikacji.Temat demonstruje, jak połączyć istniejące funkcje w czasie wykonywania współbieżności w coś ma więcej.
Ważne |
---|
W tym temacie przedstawiono pojęcia prognozy dla celów demonstracyjnych.Zaleca się używanie std::future lub concurrency::task gdy wymagają zadanie asynchroniczne, który oblicza wartość do późniejszego użycia. |
A zadania jest obliczeń, który może być rozłożony na dodatkowe, bardziej szczegółowymi obliczenia.A przyszłych jest zadanie asynchroniczne, który oblicza wartość do późniejszego użycia.
Aby zaimplementować typu futures, w tym temacie opisano async_future klasy.async_future Klasy używa tych składników Runtime współbieżności: concurrency::task_group klasy i concurrency::single_assignment klasy.async_future Klasy zastosowań task_group klasy obliczyć wartość asynchronicznie i single_assignment klasy do przechowywania wyników obliczeń.Konstruktor async_future klasa wykorzystuje funkcję pracy, która oblicza wynik, oraz get metoda pobiera wynik.
Aby zaimplementować klasę async_future
Stwierdzenie klasę szablon o nazwie async_future , jest parametryzowana typu Wynikowe obliczeń.Dodaj public i private sekcji do tej klasy.
template <typename T> class async_future { public: private: };
W private sekcji async_future klasy, oświadczyć, task_group i single_assignment elementu danych.
// Executes the asynchronous work function. task_group _tasks; // Stores the result of the asynchronous work function. single_assignment<T> _value;
W public sekcji async_future klasy, implementować konstruktora.Konstruktora jest szablon, który jest parametryzowana na funkcji pracy, która oblicza wynik.Konstruktora asynchronicznie wykonuje funkcja pracy w task_group Członkowskich danych i zastosowań concurrency::send funkcji zapisać wynik do single_assignment elementu danych.
template <class Functor> explicit async_future(Functor&& fn) { // Execute the work function in a task group and send the result // to the single_assignment object. _tasks.run([fn, this]() { send(_value, fn()); }); }
W public sekcji async_future klasy, zaimplementować destruktor.Destruktor czeka na zakończenie zadania.
~async_future() { // Wait for the task to finish. _tasks.wait(); }
W public sekcji async_future klasy, zaimplementować get metody.Metoda ta wykorzystuje concurrency::receive funkcji pobrać wynik funkcji pracy.
// Retrieves the result of the work function. // This method blocks if the async_future object is still // computing the value. T get() { return receive(_value); }
Przykład
Opis
Poniższy przykład przedstawia kompletnego async_future klasy i przykładem jego użycia.wmain Funkcja tworzy std::vector obiektu zawierającego 10 000 wartości losową liczbę całkowitą.Następnie async_future obiektów, aby znaleźć najmniejszą i największą wartość, które są zawarte w vector obiektu.
Kod
// futures.cpp
// compile with: /EHsc
#include <ppl.h>
#include <agents.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <random>
using namespace concurrency;
using namespace std;
template <typename T>
class async_future
{
public:
template <class Functor>
explicit async_future(Functor&& fn)
{
// Execute the work function in a task group and send the result
// to the single_assignment object.
_tasks.run([fn, this]() {
send(_value, fn());
});
}
~async_future()
{
// Wait for the task to finish.
_tasks.wait();
}
// Retrieves the result of the work function.
// This method blocks if the async_future object is still
// computing the value.
T get()
{
return receive(_value);
}
private:
// Executes the asynchronous work function.
task_group _tasks;
// Stores the result of the asynchronous work function.
single_assignment<T> _value;
};
int wmain()
{
// Create a vector of 10000 integers, where each element
// is between 0 and 9999.
mt19937 gen(2);
vector<int> values(10000);
generate(begin(values), end(values), [&gen]{ return gen()%10000; });
// Create a async_future object that finds the smallest value in the
// vector.
async_future<int> min_value([&]() -> int {
int smallest = INT_MAX;
for_each(begin(values), end(values), [&](int value) {
if (value < smallest)
{
smallest = value;
}
});
return smallest;
});
// Create a async_future object that finds the largest value in the
// vector.
async_future<int> max_value([&]() -> int {
int largest = INT_MIN;
for_each(begin(values), end(values), [&](int value) {
if (value > largest)
{
largest = value;
}
});
return largest;
});
// Calculate the average value of the vector while the async_future objects
// work in the background.
int sum = accumulate(begin(values), end(values), 0);
int average = sum / values.size();
// Print the smallest, largest, and average values.
wcout << L"smallest: " << min_value.get() << endl
<< L"largest: " << max_value.get() << endl
<< L"average: " << average << endl;
}
Komentarze
Ten przykład generuje następujące wyniki:
smallest: 0
largest: 9999
average: 4981
W przykładzie użyto async_future::get metoda pobierania wyniki obliczeń.async_future::get Metoda czeka na obliczeń, aby zakończyć, jeżeli obliczeń jest wciąż aktywne.
Stabilne Programowanie
Rozszerzenie async_future klasy do obsługi wyjątków, które są generowane przez funkcję pracy, modyfikowanie async_future::get wywołania metody concurrency::task_group::wait metody.task_group::wait Metoda wygeneruje wyjątkami, które zostały wygenerowane przez funkcję pracy.
W poniższym przykładzie pokazano zmodyfikowanej wersji async_future klasy.wmain Działać zastosowań try-catch bloku do drukowania wynik async_future obiektu lub do drukowania wartości wyjątek, który jest generowany przez funkcję pracy.
// futures-with-eh.cpp
// compile with: /EHsc
#include <ppl.h>
#include <agents.h>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace concurrency;
using namespace std;
template <typename T>
class async_future
{
public:
template <class Functor>
explicit async_future(Functor&& fn)
{
// Execute the work function in a task group and send the result
// to the single_assignment object.
_tasks.run([fn, this]() {
send(_value, fn());
});
}
~async_future()
{
// Wait for the task to finish.
_tasks.wait();
}
// Retrieves the result of the work function.
// This method blocks if the async_future object is still
// computing the value.
T get()
{
// Wait for the task to finish.
// The wait method throws any exceptions that were generated
// by the work function.
_tasks.wait();
// Return the result of the computation.
return receive(_value);
}
private:
// Executes the asynchronous work function.
task_group _tasks;
// Stores the result of the asynchronous work function.
single_assignment<T> _value;
};
int wmain()
{
// For illustration, create a async_future with a work
// function that throws an exception.
async_future<int> f([]() -> int {
throw exception("error");
});
// Try to read from the async_future object.
try
{
int value = f.get();
wcout << L"f contains value: " << value << endl;
}
catch (const exception& e)
{
wcout << L"caught exception: " << e.what() << endl;
}
}
Ten przykład generuje następujące wyniki:
caught exception: error
Aby uzyskać więcej informacji na temat modelu obsługi wyjątków w czasie wykonywania współbieżności, zobacz Obsługa wyjątków w Runtime współbieżności.
Kompilowanie kodu
Skopiuj przykładowy kod i wklej go w projekcie programu Visual Studio lub wkleić go w pliku o nazwie futures.cpp , a następnie uruchom następujące polecenie w oknie wiersza polecenia usługi programu Visual Studio.
cl.exe /EHsc futures.cpp
Zobacz też
Informacje
Koncepcje
Obsługa wyjątków w Runtime współbieżności