当其他线程处于活动状态并且具有 try-catch 时,无法在主线程中捕获异常
can't catch exception in main thread when other thread active and has try-catch
主线程无法捕获异常(在主线程中抛出),而另一个具有 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;
}
与其说没有捕获到异常,还不如说销毁可连接线程会终止进程。
所以你的程序在异常处理程序可以执行之前终止。
如果在 try-catch 块之外声明线程,异常将被捕获。
请记住,如果抛出异常,您还需要加入线程。
你搞错了。我是说,你误会了什么。
这不可能是试探。 'throw' 和 'try-catch' 是线程内的东西,它们只存在于当前线程,无论它在抛出时是什么,主线程或其他线程。
另一个线程无法捕获当前线程抛出的异常。异常不会跨线程,除非你真的想要它并实现它,例如,当前线程上的某些东西捕获异常并将它们传递给其他线程然后 re-throws/etc 这些异常在那里。你没有这样的东西,所以不可能。
您在抛出后有一个 join()
调用,您希望 throw 1
会跳过它。这是真的。但是,范围内还有 std::thread cThread
变量。
因为线程是 运行ning,并且由于 throw 1
线程还没有被 join()ed,那么 expected看到会是程序终止(参见), because the destructor of std::thread would detect the un-join()ed thread. That means, the std::cout << "Catched exception " << e << " in main";
should never be called. Even if the thread has somehow finished, your program should still terminate, since it does not change the fact it was not join()ed (see https://en.cppreference.com/w/cpp/thread/thread/joinable)
但是,根据库、编译器、调试器等,您看到的效果可能会有所不同。例如,如果你在调试器中 运行 它,它可能会等到所有线程完成,你会得到 "waiting until inner thread finished" 的效果。不好说。
如果您确实看到 "Catched exception " << e << "
行 运行ning,那您就遇到了真正的问题。要么您 运行 正在使用当前代码以外的东西,要么您的 stdlib 已损坏。例如,损坏的 stdlib 可能会在 std::thread 的析构函数中执行静默 join() 而不是终止程序。谁知道。损坏的库可以做很多事情。
感谢molbdnilo and quetzalcoatl。
我现在通过使用 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;
}
主线程无法捕获异常(在主线程中抛出),而另一个具有 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;
}
与其说没有捕获到异常,还不如说销毁可连接线程会终止进程。 所以你的程序在异常处理程序可以执行之前终止。
如果在 try-catch 块之外声明线程,异常将被捕获。
请记住,如果抛出异常,您还需要加入线程。
你搞错了。我是说,你误会了什么。
这不可能是试探。 'throw' 和 'try-catch' 是线程内的东西,它们只存在于当前线程,无论它在抛出时是什么,主线程或其他线程。
另一个线程无法捕获当前线程抛出的异常。异常不会跨线程,除非你真的想要它并实现它,例如,当前线程上的某些东西捕获异常并将它们传递给其他线程然后 re-throws/etc 这些异常在那里。你没有这样的东西,所以不可能。
您在抛出后有一个 join()
调用,您希望 throw 1
会跳过它。这是真的。但是,范围内还有 std::thread cThread
变量。
因为线程是 运行ning,并且由于 throw 1
线程还没有被 join()ed,那么 expected看到会是程序终止(参见), because the destructor of std::thread would detect the un-join()ed thread. That means, the std::cout << "Catched exception " << e << " in main";
should never be called. Even if the thread has somehow finished, your program should still terminate, since it does not change the fact it was not join()ed (see https://en.cppreference.com/w/cpp/thread/thread/joinable)
但是,根据库、编译器、调试器等,您看到的效果可能会有所不同。例如,如果你在调试器中 运行 它,它可能会等到所有线程完成,你会得到 "waiting until inner thread finished" 的效果。不好说。
如果您确实看到 "Catched exception " << e << "
行 运行ning,那您就遇到了真正的问题。要么您 运行 正在使用当前代码以外的东西,要么您的 stdlib 已损坏。例如,损坏的 stdlib 可能会在 std::thread 的析构函数中执行静默 join() 而不是终止程序。谁知道。损坏的库可以做很多事情。
感谢molbdnilo and quetzalcoatl。 我现在通过使用 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;
}