2013-01-08 61 views
8

我的理解是,当异步操作抛出异常时,它将被传播回调用std::future::get()的线程。但是,当这样的线程调用std::future::wait()时,异常不会立即传播 - 随后调用std::future::get()将引发异常。异常传播和std :: future

但是,在这种情况下,如果在呼叫std::future::wait()后未来对象超出范围,但在致电std::future::get()之前,会发生这种异常?

对于那些有兴趣的人,这里是一个简单的例子。在这种情况下,异常悄悄由线程/未来包处理:

#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

我_think_什么也没有发生异常,它只是被忽略。 (但是我对此一点都不熟悉,可以肯定。) – Mat

+1

我认为注意到异常是通过'std :: exception_ptr's在线程间传播的。所以对系统来说,异常看起来会被捕获和处理,直到传播机制决定重新抛出它为止。 –

回答

12

它被忽略和抛弃,就像如果你wait()一个值,但从来没有get()它。

wait()只是说“阻塞,直到未来准备就绪”,准备好一个值或例外。实际上get()的值(或例外)取决于调用者。通常你只需要使用get(),无论如何都会等待。

+0

嘎!我会买这个,但它很混乱 - 特别是如果由std :: async创建的std :: future具有void结果类型。为这样的未来调用get()感觉很奇怪。 – Bukes

+4

@Bukes:赫我可以看到。但是不要认为'未来'是'T'的结果,可以认为它是“计算'T'的结果”,这当然可能是一个例外。 – GManNickG

+0

@GManNickG如果函数返回void,那么你认为调用wait()而不是get() – Kapil

0

vs2012 \ VC11 \ CRT \ future.cpp

存在与

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

错误此代码生成一个无效acceso为 “_Future_messages”,因为 _Mycode.value()的返回4。

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

//代码示例

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; 
}