std::thread 如何判断线程已经结束

问题遇到的现象和发生背景

程序有一个比较耗时的连接线程Connect()

在1s的定时器中,判断是否是否连接失败了,如果连接失败了就再调用Connect。在这里该如何判断Connect是否已经执行完毕呢?

直接使用Join阻塞了定时器并不可取。

我的解答思路和尝试过的方法

我的思路是加个正在连接标志,连接之前true,连接完成后false。当定时器中检测到false的时候再执行join,但发现还是有一定时间的阻塞。

我想要达到的结果

这个该如何解决?

不放代码确实不明白你的程序逻辑, 如果是我设计一个 connect 函数, 会返回一个 bool 看是否连接成功, 耗时阻塞没有问题, 放 promise 里, 不用定时器, 直接用 future wait 1 秒, 如果 ready 就 get value, true 就干接下来的事, false 就 接着 connect, 如果 future wait 1 秒没有 ready, 再分情况讨论, 继续等, 或其它. 有定时器逻辑差不多, 只不过必须死等 1 秒, 再次判断.

#include <chrono>
#include <iostream>

auto Connect() -> bool
{
    return true;
}

void doSomething()
{
    std::cout << "OK" << std::endl;
}

void doOthers()
{
    std::cout << "PlanB" << std::endl;
}

auto main() -> int
{
    std::promise<bool> prms;

    std::future<bool> ftr = prms.get_future();

    std::thread thrd([prms = std::move(prms)]() mutable {
        bool const connectSuccess = Connect();
        prms.set_value(connectSuccess);
    });

    thrd.detach();

    std::this_thread::sleep_for(std::chrono::seconds(1));

    if ((ftr.wait_for(std::chrono::seconds(0)) == std::future_status::ready) &&
        ftr.get())
    {
        doSomething();
    }
    else
    {
        doOthers();
    }

    return 0;
}

这种最好把connect fd设置非阻塞模式。然后再结合定时器。如果connect失败在非阻塞模式下会立即返回 再起动定时1秒后重新连

可以利用信号来处理
https://blog.csdn.net/m0_56827172/article/details/124895395

不知这里提到的方法思路是否能帮到你,链接:https://segmentfault.com/q/1010000042693101/

参考链接

用标志位变量可以解决的,定时器检测造成的延时最长就1s左右。如果你的需求是线程退出就要立马告诉其他线程进行join处理的话,要么有一个线程join等待,要是Linux环境下的,可以使用信号

1 不使用线程池的情况下
调用Thread.isAlive()方法,如果该线程没有执行完毕,会返回true;
调用Thread.activeCount()方法,返回当前线程组的运行线程数量,一般是1,可是IDEA执行用户代码的时候,实际是通过反射方式去调用,而与此同时会创建一个Monitor Ctrl-Break 用于监控目的。
2 使用线程池的情况下
在线程池的线程启动后,执行线程池的shutdown()方法,该方法表示当线程池中所有线程都运行完毕后就关闭线程池。再使用线程池的isTerminated()方法判断线程池是否已经关闭判断线程是否执行完毕。
使用一些信号量,比如CountDownLatch或者condition等。

这场景就是多线程同步。
Connect既然是阻塞模式,它应该有超时时间参数(这种是常规套路);否则调用后就一直等待,直到连接成功。
通常可以使用std::mutex+std::condition_variable来完成C++11多线程之间的同步操作,比如:
在你的等待线程T1中,创建并启动了连接线程T2(Connect业务);
T1中启动T2成功后,进入等待状态,直到收到T2连接成功的事件通知,接着处理后续逻辑;
T2线程函数中While循环调用Connect(超时调用),通过返回值可以判断是否连接成功,若连接成功,cv.notify_one通知T1,结束T2线程;若没连接成功,进入下一次Connect。


std::mutex+std::condition_variable的具体用法,可以参考这篇博客,用法比较简单
https://blog.csdn.net/zengyubao1/article/details/112754693

参考一下

1,优化代码设计,避免这种情况
2,使用状态机来控制流程运行
3,使用条件变量进行事件通知

用个代理,给一个触发点,我之前用线程thread和定时器配合不怎么好用