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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM