简体   繁体   English

如何在退出之前重新连接线程或等待线程完成

[英]How to reattach thread or wait for thread completion before exiting

I have an application that connects to a socket using the asio library. 我有一个使用asio库连接到套接字的应用程序。 My main thread calls an open() to the socket implementation where it is then detached from the main thread to continue execution. 我的主线程向套接字实现调用open() ,然后将其与主线程分离以继续执行。

When thread::detach() is called, the thread can no longer be joined and thus the caller has no idea when the thread has completed its execution. 调用thread::detach() ,无法再连接线程,因此调用者不知道线程何时完成其执行。 This results, at least in my application, of an unclean shutdown. 至少在我的应用程序中,这会导致异常关闭。 Resources aren't deallocated properly and, only sometimes, leads to a crash. 资源未正确释放,仅在某些情况下会导致崩溃。 Is it possible to rejoin the detached thread? 是否可以重新加入分离的线程? I would like to try and avoid using a condition variable. 我想尝试避免使用条件变量。

Here is my example: 这是我的示例:

io_socket io = new io_socket();

// The call to thread::detach() is done within io_socket::open()
io->open();

// Let some things happen...
std::this_thread::sleep_for(std::chrono::seconds(20));

// Safely kills all operations and resources before delete
io->close();

// A hack solution to allow time for the detached thread to do what it needs to do
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));

// Crashes if I don't allow the detached thread to safely close
delete io;

return EXIT_SUCCESS;

You cannot reattach a std::thread that you have detached. 您不能重新附加已分离的std::thread The only way to wait for a detach thread to end is to use some sort of atomic/condition variable to notify you when it it done. 等待分离线程结束的唯一方法是使用某种原子/条件变量在完成时通知您。

That said, you probably don't need to detach the thread in the first place. 就是说,您可能首先不需要分离线程。 What you can do is create storage for the threads to live in ( std::vector<std::thread> comes to mind) and then in open you add the new thread to that storage. 您可以做的是为要std::vector<std::thread>的线程创建存储(想到的是std::vector<std::thread> ),然后在open时将新线程添加到该存储中。 Once you are all done you call close and have close go through every thread in the storage and call join on it. 完成所有操作后,您将调用closeclose访问存储中的每个线程,并在其上调用join This will make close your synchronization point and after that you know that all threads have ended and you are safe to close the application. 这将close您的同步点,此后您将知道所有线程都已结束并且可以安全地关闭应用程序。

Assuming that the IO thread is coded by you, you can handle this with a combination of std::promise and std::future , something like this: 假设IO线程是由您编写的,则可以使用std::promisestd::future的组合来处理此问题,如下所示:

#include <chrono>
#include <thread>
#include <future>
#include <iostream>

using namespace std::chrono_literals;

void demo_thread (std::promise <bool> *p)
{
    std::cout << "demo thread waiting...\n";
    std::this_thread::sleep_for (1000ms);
    std::cout << "demo thread terminating\n";
    p->set_value (true);
}

int main ()
{
    std::promise <bool> p;
    std::thread t = std::thread (demo_thread, &p);
    t.detach ();

    // ...

    std::cout << "main thread waiting...\n";
    std::future <bool> f = p.get_future();
    f.wait ();

    std::cout << "main thread terminating\n";
}

Live demo 现场演示

Is it possible to rejoin the detached thread? 是否可以重新加入分离的线程?

No. That would defeat the whole purpose of detach() . 不。那会detach()的整个目的。

A t.detach() call does not actually do anything essential. t.detach()调用实际上并没有做任何必要的事情。 It's only purpose is to disable a safety mechanism. 唯一的目的是禁用安全机制。

Normally, if you don't detach() a thread, then the destructor for the thread object will throw an error if you allow the object to be destroyed before your program has join()ed it. 通常,如果不detach()线程,则如果允许在程序join()ed之前销毁对象,则该thread对象的析构函数将引发错误。 The only purpose for that is to help you to avoid a common mistake: It's meant to prevent your main() routine from exiting and terminating the program before all of the other threads have finished. 这样做的唯一目的是帮助您避免一个常见的错误:这是为了防止main()例程在所有其他线程完成之前退出并终止程序。

The purpose of t.detach() ---the only purpose---is to tell the library, "Thanks, but I know what I'm doing, I don't want the help, and I am NEVER going to call t.join() . t.detach()的目的是唯一的目的,它是告诉库:“谢谢,但是我知道我在做什么,我不想要帮助,我永远也不会打电话给我t.join()


If you want your program to call t.join() then don't call t.detach() . 如果要让程序调用t.join()则不要调用t.detach()

NathanOliver has provided a good answer, but his solution may prove difficult if the io->open() function does not return a reference to the std::thread object it creates (which, if it detaches, it likely doesn't). NathanOliver提供了一个很好的答案,但是,如果io->open()函数未返回对其创建的std :: thread对象的引用(如果分离,则可能不会),则他的解决方案可能会很困难。 If you are using the Asio library directly, I would expect that io->close() should be properly handling graceful exit of the thread before you delete io . 如果直接使用Asio库,我希望io->close()应该在删除io之前正确处理线程的正常退出。 However, if this is a wrapper you've implemented, you either need to return a reference to the created thread object in open() , or change your implementation of close() so that it blocks until the resources have actually been deallocated. 但是,如果这是您实现的包装器,则您需要在open()返回对创建的线程对象的引用,或者更改您对close()实现,以使其阻塞,直到实际释放资源为止。 Furthermore, if these are methods implemented yourself, is the detach in open() even necessary? 此外,如果这些是您自己实现的方法,则open()的分离是否必要?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在退出主线程之前等待异步文件写入完成 - Wait for async file write to finish before exiting main thread 在退出关联线程之前关闭线程句柄 - Closing a thread handle before exiting the associated thread 等待线程完成而不冻结MFC中的UI - Wait for thread completion without freezing the UI in MFC future :: wait()是否同步 - 是否通过async()完成执行的线程? - Does future::wait() synchronize-with completion of the thread of execution by async()? 通知线程是否可以在通知线程等待锁定之前锁定? - Is it possible for the notifying thread to lock before the notified thread's wait to lock? C ++允许后台线程在退出应用程序之前完成 - c++ allow background thread to finish before exiting application 如何正确等待线程中的信号 - How to wait properly for a signal in a thread 将鼠标光标更改为等待光标,然后启动工作线程并在线程完成时改回 - changing mouse cursor to wait cursor then starting worker thread and changing back on thread completion 在退出c ++ pthread中的线程之前调用mysql_thread_end函数 - calling mysql_thread_end function before exiting the thread in c++ pthread 在wxwidgets中,如何使一个线程在完成之前等待另一个线程完成? - In wxwidgets, how do I make one thread wait for another to complete before proceeding?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM