当其他线程处于活动状态且具有try-catch时,无法在主线程中捕获异常

问题描述 投票:1回答:3

主线程无法捕获异常(在主线程中抛出),而另一个具有try-catch的线程仍处于活动状态。怎么解决?例:

int main()
{
  // try-catch of main thread
  try
  {
     // run a thread
     std::thread cThread([]()
     {
        // try-catch of secondary thread
        try
        {
           // makes thread works for 500 ms in order main thread will call
           // throw while thread is still active.  
           std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
        catch (...)
        {
        }
     });

     // Any call to throw BEFORE thread is finished, won't be catch.  
     // HOW TO SOLVE IT??
     throw 1;

     // wait thread finished
     cThread.join();

     // IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE 
     // CATCH.
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}
c++ multithreading exception throw
3个回答
3
投票

并不是因为破坏可连接线程终止进程而没有捕获异常。因此,在执行异常处理程序之前,程序将终止。

如果在try-catch块之外声明该线程,则会捕获该异常。 请记住,如果抛出异常,您还需要加入该线程。


2
投票

你错了。我的意思是,你误会了什么。

它不能是关于try-catch。 'throw'和'try-catch'是线程内的东西,它们只存在于当前线程中,无论它在抛出,主线程还是其他时刻都是如此。

另一个线程无法捕获当前线程抛出的异常。异常不会跨越线程,除非你真的想要并实现它,例如,当前线程上的某些东西捕获异常并将它们传递给其他线程然后重新抛出/ etc这些异常。你没有任何这样的东西,所以不可能。

投掷后你有一个join()跟注,你期望throw 1会跳过它。确实如此。但是,范围内还有std::thread cThread变量。

由于线程正在运行,并且由于throw 1线程从未进行过join()编辑,所以预期要看的是程序终止(参见https://stackoverflow.com/a/13984169/717732),因为std :: thread的析构函数会检测到un-join ()ed线程。这意味着,永远不应该召唤std::cout << "Catched exception " << e << " in main";。即使线程以某种方式完成,你的程序仍然应该终止,因为它不会改变它不是join()ed的事实(参见https://en.cppreference.com/w/cpp/thread/thread/joinable

但是,根据库,编译器,调试器等,您看到的效果可能会有所不同。例如,如果您在调试器中运行它,它可能会等到所有线程完成,并且您将获得“等待内部线程完成”的效果。很难说。

如果你真的看到"Catched exception " << e << "线正在运行,你就会遇到一个真正的问题。您运行的是其他内容而不是当前代码,或者您的stdlib已损坏。例如,破坏的stdlib可能会在std :: thread的析构函数中执行静默join(),而不是终止程序。谁知道。破碎的lib可以做很多事情。


0
投票

感谢molbdniloquetzalcoatl。我现在通过使用std :: async而不是std :: thread来使代码工作:

首先,问题与线程中的try-catch无关。我认为这是错误的。所以这是一个失败代码:

int main()
{
  // try-catch of main thread
  try
  {
     // run a thread
     std::thread cThread([]()
     {
     });

     // Any call to throw BEFORE thread join won't be catch.  
     // HOW TO SOLVE IT??
     throw 1;

     // wait thread finished
     cThread.join();

     // IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE 
     // CATCH.
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}

一个有效的代码:

int main()
{
  std::future<void> cF;

  // try-catch of main thread
  try
  {
     // run a thread
     cF = std::async(std::launch::async, []()
     {
     });

     // You can call throw , it will be catch :)  
     throw 1;

     // wait thread finished
     if (cF.valid())
     {
        cF.get();
     }
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.