не может перехватить исключение в основном потоке, когда другой поток активен и имеет try-catch - PullRequest
1 голос
/ 10 апреля 2019

Основной поток не может перехватить исключение (которое было сгенерировано в основном потоке), в то время как другой поток с 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;
}

Ответы [ 3 ]

3 голосов
/ 10 апреля 2019

Дело не в том, что исключение не перехватывается, а в том, что уничтожение присоединяемого потока завершает процесс.Таким образом, ваша программа завершает работу до того, как может быть выполнен обработчик исключения.

Если вы объявите поток вне блока try-catch, исключение будет перехвачено.
Помните, что вам также необходимо присоединиться к потоку, еслиисключение было брошено.

2 голосов
/ 10 апреля 2019

У вас что-то не так.Я имею в виду, вы что-то неправильно поняли.

Это не может быть попыткой поймать.'throw' и 'try-catch' являются вещами внутри потока, они живут только в текущем потоке, каким бы он ни был в момент выброса, основным потоком или другим.

Другой поток не может перехватить исключениевыброшенный из текущей темы.Исключения не пересекают потоки, если вы действительно не хотите этого и не реализуете его, как, например, что-то в текущем потоке, перехватывает исключение и передает их другому потоку, а затем повторно выдает / etc эти исключения там.У вас нет таких вещей, поэтому это не может быть.

У вас есть join() вызов после броска, и вы ожидаете, что throw 1 пропустит его.Это правда.Однако в области видимости также есть переменная std::thread cThread.

Поскольку поток работает и из-за throw 1 поток еще ни разу не был присоединен (), то ожидается 1015 * завершение программы (см. 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 не работает. Aсломанный stdlib может на экзаменПожалуйста, сделайте тихое соединение () в деструкторе std :: thread вместо завершения программы.Кто знает.Сломанная библиотека может сделать много вещей.

0 голосов
/ 10 апреля 2019

Благодаря molbdnilo и кетцалькоатль .Теперь я заставил код работать, используя 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...