c/c++ 多线程 等待一次性事件 异常处理

多线程 等待一次性事件 异常处理

背景:假设某个future在等待另一个线程结束,但是在被future等待的线程里发生了异常(throw一个异常A),这时怎么处理。

结果:假设发生了上面的场景,则在调用future的get方法时,就会得到被future等待的线程抛出的异常A。

3种情况:

1,std::async

2,std::packaged_task

3,std::promise,知道发生异常了,可以不调用set_value,而是调用set_exception(std::current_exception());

代码:

#include <iostream>
#include <string>
#include <future>

class A{
  int data;
public:
  A(int d = 10) : data(d){}
  int _data() const {return data;}
};
double div1(double a, double b){
  if(b == 0){
    //throw std::string("error");//进入string的catch
    //throw "error";//进入const char*的catch
    //throw 1;//进入int的catch
    throw A(101);//进入A a的catch
    
  }
  return a / b;
}

double div2(std::promise<double>& pro, double a, double b){
    int x;
    std::cin.exceptions (std::ios::failbit);   //如果不加这句,std::cin >> x这里,即使给的不是数字,也不会发生异常。
    try{
      std::cin >> x;//输入一个字母,就会引发异常
    }catch(std::exception&){
      pro.set_exception(std::current_exception());
    }

}
int main(){
  try{

    //std::asnyc 执行这段时,把后面的std::package_task和std::promise注释掉
    std::future<double> f = std::async(div1, 10, 0);
    std::cout << f.get() << std::endl;//get如果发生了异常,则进入catch

    //std::package_task 执行这段时,把std::asnyc和td::promise注释掉
    std::packaged_task<double(double, double)> t(div1);
    std::future<double> f2 = t.get_future();
    std::thread thread1(std::ref(t), 100, 0);
    thread1.detach();
    f2.get();//get如果发生了异常,则进入catch

    //std::promise 执行这段时,把上面的std::asnyc和td::package_task注释掉
    std::promise<double> pro;
    std::future<double> f3 = pro.get_future();
    std::thread thread2(div2, std::ref(pro), 100, 0);
    thread2.join();
    f3.get();////get如果发生了异常,则进入catch(...)部分
    
  }
  catch(A a){
    std::cout << "err:A a" << std::endl;
    std::cout << a._data() << std::endl;
  }
  catch(int a){
    std::cout << "err:int" << std::endl;
    std::cout << a << std::endl;
  }
  catch(const char* s){
    std::cout << "err:char*" << std::endl;
    std::cout << s << std::endl;
  }
  catch(std::string s){
    std::cout << "err:string" << std::endl;
    std::cout << s << std::endl;
  }
  catch(...){
    using namespace std;
    cout << "...." << endl;
    
  }
}

github源代码

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

posted @ 2018-11-26 22:39  小石王  阅读(1403)  评论(0编辑  收藏  举报