230703 Cpp multi-threading exception on Windows
在工作的时候遇到了exception如果发生在std::thread里面整个程序会直接崩溃的问题。
Conclusion
感觉要么自己在thread里处理好exception,或者自己包装一下thread(配合promise使用),要么用更高级的API,可以返回运行结果或者exception。
When exception happens in a running std::thread
if use std::thread, an exception occurs and not catched inside thread
If no matching handler is found, the function std::terminate() is called
https://stackoverflow.com/a/7272147
https://en.cppreference.com/w/cpp/thread/thread
By default, terminate() will call abort()
- cannot catch exception outside the thread where the exception happens
No you most definitely cannot catch an exception outside of its “thread or origin”. The exception catching depends on stack unwinding, and stack is fundamentally thread-specific.
https://stackoverflow.com/a/7272147
didn’t find a source for “exception catching depends on stack unwinding”
- use std::async instead of std::thread
1 | auto run = []() -> T // T may be void as above |
this way we can get the exception by launched.get()
in the parent thread. if not call get(), exception will be ignored (I tested).
However, async() does not guarantee to use a separate thread
- maybe use std::thread with std::promise and std::future, create a wrapper
Use Threading API (Microsoft’s PPL) rather than plain std::thread
std::async also use PPL API?
This answer also says concurrency::task
has lower efficiency, compared to self-made thread pool with std::thread
and std::promise
.
While, in MS document, it only says async use Windows thread pool, and non-conforming with C++ standard
The C++ standard states that if policy is launch::async, the function creates a new thread. However the Microsoft implementation is currently non-conforming. It obtains its threads from the Windows ThreadPool, which in some cases may provide a recycled thread rather than a new one. This means that the launch::async policy is implemented as launch::async|launch::deferred. Another implication of the ThreadPool-based implementation is that there’s no guarantee that thread-local variables will be destroyed when the thread completes. If the thread is recycled and provided to a new call to async, the old variables will still exist. We recommend that you don’t use thread-local variables with async.
https://learn.microsoft.com/en-us/cpp/standard-library/future-functions?view=msvc-170#async
thread pool
thread pool is to better and easier manage the computing resource