C++ Visual Studio 2013(Windows8.1)和GCC 4.9(Ubuntu14.10)异步的不同行为

C++ Visual Studio 2013(Windows8.1)和GCC 4.9(Ubuntu14.10)异步的不同行为,c++,linux,multithreading,c++11,gcc,C++,Linux,Multithreading,C++11,Gcc,异步在Windows和Linux g++中有不同的行为(实现) 我使用以下代码对其进行了测试: void Func1(){sleep(1000*1000);} void Func2(){sleep(1000*2);throw runtime_error("An expected exception");} int main(int argc, char* argv[]){ try{ auto f1 = async(launch::async, Func1);

异步在Windows和Linux g++中有不同的行为(实现)

我使用以下代码对其进行了测试:

void Func1(){sleep(1000*1000);}
void Func2(){sleep(1000*2);throw runtime_error("An expected exception");}


int main(int argc, char* argv[]){
  try{
    auto f1 = async(launch::async, Func1);
    auto f2 = async(launch::async, Func2);

    f2.get();//block here
    f1.get();
  }catch (exception& e){
    printf("exception: %s\n", e.what());
  }
  return 0;
}
Func1在启动后会长时间睡眠

Func2将抛出一个异常

我的观察是:

在Windows中,异常会立即传播,主线程(程序)将捕获它并相应地退出

在Linux中,异常保持打开状态,直到Func1中的睡眠1000秒结束,程序才会退出


那么,在Linux中,有人知道如何让程序立即捕获异常并退出程序吗???

尝试在
Func1
Func2
中比较以下结果:

std::cout << std::this_thread::get_id() << std::endl;

请参见我关于
std::packaged_task

上的
future
的回答,从
async
获得的
具有阻塞析构函数。这一“特征”极具争议性,标准委员会对此进行了多次讨论。例如,请参见这个SO问题:这种行为的原因是没有好的可移植方法来终止线程

然后
f2
抛出一个异常,调用
f1
的析构函数,该析构函数将等待踏板(从而
Func1
)完成。因此,
catch
块仅在
Func1
完成后执行

对于Windows行为,这是一个已知的VC++错误,如下所述:

因此,Linux上的GCC是正确的,而Windows上的VC++是错误的


有关解决方法,请参见,例如,Linux编译器中听起来像个bug,但当您的代码有
睡眠(1000*1000)
时,您说“直到Func1中的睡眠1000秒结束才退出”(刚刚超过11天)在C++11中,不要只使用
sleep
而使用
std::this\u thread::sleep\u for
请注意,在Windows上,sleep
以毫秒为参数,在linux上则以秒为参数。因此,在linux上,此代码的等待时间预计要长1000倍。这就是为什么您应该为
使用标准的
std::this_thread::sleep\u-因为平台之间的睡眠并不标准化,有些需要几秒钟,有些需要几毫秒来避免分心,请将此代码片段视为伪代码。在我的代码中,我使用了一个名为mySleep的函数,它是sleep_的内联函数,但为了简单起见,我在这里使用sleep,因为它不会改变我所问问题的性质。我也没有包括头文件。谢谢。如果显式指定了launch::async策略,那么任务实际上保证“像在一个新线程中一样”执行,这使得这个答案是错误的。见§30.6.8/3(N3376)。线程ID可能与已完成的先前async()中的相同,但这并不能证明什么,因为标准只承诺新线程的ID在现有线程中是唯一的,而不是先前存在的线程(N3376中的§30.3.2/1)。对,真正的原因是catch阻塞之前的阻塞
future
析构函数
std::packaged_task< int(int) > package{ Func2 };
std::future<void> f2 = package.get_future();
std::thread t { std::move(package) };

f2.get();       //block here until t finishes

t.join();