2013-01-08 14 views
8

Rozumiem, że gdy operacja asynchroniczna zgłasza wyjątek, zostanie ona propagowana z powrotem do wątku, który wywołuje std::future::get(). Jednakże, gdy taki wątek wywołuje std::future::wait(), wyjątek nie jest natychmiast propagowany - zostanie zgłoszony podczas kolejnego wywołania std::future::get().Rozsyłanie wyjątków i std :: future

Jednak w takim scenariuszu, co ma stać się z takim wyjątkiem, jeśli przyszły obiekt wykracza poza zakres po wywołaniu std::future::wait(), ale przed wywołaniem do std::future::get()?

Dla zainteresowanych, oto prosty przykład. W tym przypadku wyjątek jest cicho obsługiwane przez gwintu/pakiet przyszłości:

#include "stdafx.h" 
#include <thread> 
#include <future> 
#include <iostream> 

int32_t DoWork(int32_t i) 
{ 
    std::cout << "i == " << i << std::endl; 
    throw std::runtime_error("DoWork test exception"); 
    return 0; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    auto f = std::async(DoWork, 5); 
    try 
    { 
     //f.get();  // 1 - Exception does propagate. 
     f.wait();  // 2 - Exception does NOT propagate. 
    } 
    catch(std::exception& e) 
    { 
     std::cout << e.what() << std::endl; 
     return -1; 
    } 
    return 0; 
} 
+0

Ithink_ nic nie dzieje się z wyjątkiem, po prostu zostaje zignorowany. (Ale nie jestem dostatecznie zaznajomiony z tym, aby być pewnym.) – Mat

+1

Sądzę, że ważne jest, aby zauważyć, że wyjątki są propagowane w wątkach przez 'std :: exception_ptr's. Tak więc do systemu wyjątek wygląda na zaczepiony i obsługiwany, dopóki mechanizm propagacji nie zdecyduje się go ponownie rzucić. –

Odpowiedz

12

To jest ignorowane i odrzucane, podobnie jak jeśli wait() dla wartości, ale nigdy get() nim.

wait() po prostu mówi "blokuj do przyszłości", bądź gotowa z wartością lub wyjątkiem. Od osoby wywołującej zależy wartość (lub wyjątek). Zwykle po prostu użyjesz get(), która i tak czeka.

+0

Gah! Kupię to, ale jest to mylące - zwłaszcza jeśli std :: future stworzony przez std :: async ma typ wyniku pustego. Wywoływanie get() na taką przyszłość wydaje się dziwne. – Bukes

+4

@Bukes: Heh Widziałem to. Ale nie myśl o 'przyszłości ' jako "wyniku' T' ", pomyśl o tym jako" wyniku obliczenia 'T'", co oczywiście może być wyjątkiem. – GManNickG

+0

@GManNickG co, jeśli funkcja zwraca pustkę, czy nie uważasz, że sensowne jest wywołanie wait() zamiast get() – Kapil

0

vs2012 \ vc11 \ crt \ future.cpp

występuje błąd w

static const char *const _Future_messages[] = 
{ // messages for future errors 
"broken promise", 
"future already retrieved", 
"promise already satisfied", 
"no state" 
}; 

to wygenerowany kod nieprawidłowy acceso do "_Future_messages", ponieważ _Mycode.value() zwrotny 4.

const char *__CLR_OR_THIS_CALL what() const _THROW0() 
    { // get message string 
    return (_Get_future_error_what(_Mycode.value())); 
    } 

// przykładowy kod

std::future<int> empty; 
try { 
    int n = empty.get(); 
} catch (const std::future_error& e) { 
    const error_code eCode = e.code(); 
    char *sValue = (char*)e.what(); 
    std::cout << "Caught a future_error with code " << eCode.message() 
       << " - what" << sValue << endl; 
}