在msvc上,如果你试图加入一个不可连接的线程,它将调用abort。所以你必须在调用join之前检查该线程是否可以连接,但是这里的self是一个竞争条件。
void BaseThread::join()
{
auto thread = m_pPrivates->m_pThread;
if (!thread)
return;
if (thread->get_id() != std::thread::id() && thread->joinable())
thread->join();
}
如果线程不可连接或更好的方法,是否可以停止调用abort的运行时间?
编辑:
所以这是在visual studio运行时处理线程关闭的函数。
int _Thrd_join(_Thrd_t thr, int *code)
{ /* return exit code when thread terminates */
unsigned long res;
if (WaitForSingleObject(thr._Hnd, INFINITE) == WAIT_FAILED || GetExitCodeThread(thr._Hnd, &res) == 0)
return (_Thrd_error);
if (code)
*code = (int)res;
return (CloseHandle(thr._Hnd) == 0 ? _Thrd_error : _Thrd_success);
}
最后一行(CloseHandle)抛出此异常:
Unhandled exception at 0x7750BCEC (ntdll.dll) in desura.exe: 0xC0000008: An invalid handle was specified. Which then crashes the app
答案 0 :(得分:5)
它本身并不是一种竞争条件。线程保持可连接状态,直到它被连接,分离或移动为止。这些是你的程序可以控制的所有东西,如果另一个线程正在与你尝试加入的线程异步地执行其中一项,你显然必须同步。但通常情况并非如此,而且您是该主题的所有者/经理。
请注意,仅仅因为线程完成执行,这不会使其无法加入。实际上,即使您可以保证线程已经完成执行,您仍然必须加入它(或分离它等)以防止被调用terminate()
。
答案 1 :(得分:0)
请参阅上面的评论。请注意,std::thread
具有与pthread
库非常相似的界面/行为,因此即使pthread
,我对std::thread
的评论也有效。
您应该在线程上使用的两个操作是“开始”和“加入”。如果您正在使用其他东西或者您正在考虑使用其他东西,那么您的设计就不行了,是时候发布一个关于您的实际线程问题的问题,而不是转向一个糟糕的设计并要求其他人“推动它更难”。 :-) :-): - )
许多线程API /库除了“开始”和“加入”之外还包含几个附加功能,但这些通常只是为了鼓励糟糕的线程设计。在我看来,std::thread::joinable()
和线程对象的移动也是没有的东西......