我有以下功能:
void threadProc(){
for (int i = 0; i < 5; ++i) {
std::cout << "\n thread #" << std::this_thread::get_id() << " says hi";
}
std::cout << "\n Finished executing thread #" << std::this_thread::get_id();
}
我正在以下列方式使用它:
int main(){
try {
std::thread t1(threadProc);
t1.join();
std::thread t2(threadProc);
HANDLE handle = t2.native_handle();
WaitForSingleObject(handle, INFINITE);
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "\n thread t2 is joinable: " << std::boolalpha << t2.joinable() << "\n\n";
}
catch (std::exception& ex){
std::cout << "\n\n " << ex.what() << "\n\n";
}
return 0;
}
这是输出:
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
完成执行线程#21300
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
完成执行线程#2136
线程t2是可连接的:true
然后当try块超出范围时崩溃,因为在abort()
上调用了t2
。
我的问题是,即使t2
结束,为什么joinable()
仍然threadProc
?为什么没有完成处理?
此外,我正在使用WaitForSingleObject
来确保我等到t2
完成处理。我还添加了5秒等待,以确保它花费时间来完成其处理。然而,有些事情仍未完成。
我知道我可以使用t2.join()
或t2.detach()
但我为什么要这样做? t2
已经完成处理(我认为)。
编辑:我尝试了以下代码:
int main() {
try {
std::thread t1([]() {std::cout << "\n\n Hi from thread #" << std::this_thread::get_id(); });
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
catch (std::exception& ex) {
std::cout << "\n\n " << ex.what() << "\n\n";
}
return 0;
}
仍然可以加入线程。我查了joinable
引用,他们说:
已完成执行代码但尚未加入的线程仍被视为活动执行线程,因此可以加入。
因此,这与WaitForSingleObject
无关。问题是为什么一个线程在完成执行后仍然被认为是joinable()
?
我已经看到这个question让我更加困惑,因为它表明当线程完成执行时,即使在调用joinable()
或join()
之前,它也不是detach()
。
答案 0 :(得分:5)
问题是为什么线程在完成执行后仍然被认为是joinable()?
因为你可能想编写join()的代码。如果t.joinable()
在终止时自动变为假,则无法安全地致电t.join()
。你可以这样写:
if (t.joinable()) {
t.join();
}
但是,如果线程在t.joinable()
返回true
之后终止,但在调用者能够完成t.join()
调用之前终止,则仍会抛出异常。
让线程保持可连接状态,直到它实际上是join()ed是更简单的描述行为,并且编写正确使用它的代码更容易。
答案 1 :(得分:4)
joinable
并不意味着still_running
,可加入只是意味着线程对象不是&#34;空&#34; (作为默认构造或移动的结果)并且与实际的OS执行线程相关联。
如果线程为空,则意味着没有任何东西可以加入,因此,线程不是&#34;可加入&#34;。
如果线程不为空,则可以使当前线程等待它,因此它是&#34;可加入&#34;。