如何在不使用 Sleep() 的情况下让线程自行等待?

How to let a thread wait itself out without using Sleep()?

我想让线程中的while循环到运行,稍等一下,然后再运行,依此类推,但是这似乎不起作用,怎么办我修好了吗?

main(){
    bool flag = true;
    pthread = CreateThread(NULL, 0, ThreadFun, this, 0, &ThreadIP);
    
}
ThreadFun(){
    while(flag == true)
        WaitForSingleObject(pthread,1000); 
}

这是一种方法,我更喜欢使用条件变量而不是睡眠,因为它们响应更快,std::async 优于 std::thread(主要是因为 std::async returns可以将信息发送回起始线程的未来。即使此示例中未使用该功能)。

#include <iostream>
#include <chrono>
#include <future>
#include <condition_variable>

// A very useful primitive to communicate between threads is the condition_variable
// despite its name it isn't a variable perse. It is more of an interthread signal
// saying, hey wake up thread something may have changed that's interesting to you.
// They come with some conditions of their own
// - always use with a lock
// - never wait without a predicate
// (https://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables)
// - have some state to observe (in this case just a bool)
// 
// Since these three things go together I usually pack them in a class
// in this case signal_t which will be used to let thread signal each other

class signal_t
{
public:
    // wait for boolean to become true, or until a certain time period has passed
    // then return the value of the boolean.
    bool wait_for(const std::chrono::steady_clock::duration& duration)
    {
        std::unique_lock<std::mutex> lock{ m_mtx };
        m_cv.wait_for(lock, duration, [&] { return m_signal; });
        return m_signal;
    }

    // wiat until the boolean becomes true, wait infinitely long if needed
    void wait()
    {
        std::unique_lock<std::mutex> lock{ m_mtx };
        m_cv.wait(lock, [&] {return m_signal; });
    }
    
    // set the signal
    void set()
    {
        std::unique_lock<std::mutex> lock{ m_mtx };
        m_signal = true;
        m_cv.notify_all();
    }

private:
    bool m_signal { false };
    std::mutex m_mtx;
    std::condition_variable m_cv;
};

int main()
{
    // create two signals to let mainthread and loopthread communicate
    signal_t started; // indicates that loop has really started
    signal_t stop;    // lets mainthread communicate a stop signal to the loop thread.

    // in this example I use a lambda to implement the loop
    auto future = std::async(std::launch::async, [&]
    {
        // signal this thread has been scheduled and has started.
        started.set();

        do
        {
            std::cout << ".";

            // the stop_wait_for will either wait 500 ms and return false
            // or stop immediately when stop signal is set and then return true
            // the wait with condition variables is much more responsive
            // then implementing a loop with sleep (which will only
            // check stop condition every 500ms)
        } while (!stop.wait_for(std::chrono::milliseconds(500)));
    });

    // wait for loop to have started
    started.wait();
    
    // give the thread some time to run
    std::this_thread::sleep_for(std::chrono::seconds(3));

    // then signal the loop to stop
    stop.set();

    // synchronize with thread stop
    future.get();

    return 0;
}

虽然另一个答案是一种可能的方法,但我的答案主要是从不同的角度回答,试图看看您的代码可能有什么问题...

好吧,如果你不想在 flag 设置为 false 时等待一秒钟,并且你想要至少延迟 1000 毫秒,那么使用 Sleep 可以,但是 你需要

  • 一个原子变量(例如 std::atomic
  • 或函数(例如InterlockedCompareExchange
  • MemoryBarrier
  • 或其他一些同步方式来检查标志。

如果没有适当的同步,则无法保证编译器会从内存而不是缓存或寄存器中读取值。

同时使用 Sleep 或来自 UI 线程的类似函数也是可疑的。

对于控制台应用程序,如果您的应用程序的目的确实是在给定的持续时间内工作,您可以在主线程中等待一段时间。但通常,您可能希望等到处理完成。在大多数情况下,您通常应该等待您启动的线程完成。

Sleep函数的另一个问题是,即使无事可做,线程也总是每隔几秒就必须唤醒一次。如果您想优化电池使用,这可能会很糟糕。但是,另一方面,如果您的代码中存在一些错误,则等待某个信号(句柄)的函数超时时间相对较长可能会使您的代码更加健壮,以防止错过唤醒。

在某些情况下,您还需要延迟,您实际上没有什么可等待的,但您需要定期提取一些数据。

大超时也可用作一种看门狗计时器。例如,如果您希望有事可做但在很长一段时间内什么也得不到,您可以以某种方式报告警告,以便用户可以检查是否有什么不正常。

I highly recommand you to read a book on multithreading like Concurrency in Action before writing multithread code code.

Without proper understanding of multithreading, it is almost 100% certain that anyone code is bugged. You need to properly understand the C++ memory model (https://en.cppreference.com/w/cpp/language/memory_model) to write correct code.

等待自身的线程没有意义。当您等待一个线程时,您是在等待它终止,显然 如果它已终止,那么它就不能执行您的代码。您的主线程应该等待后台线程终止。

我通常还建议在 API 上使用 C++ 线程函数,因为它们:

  • 使您的代码可移植到其他系统。
  • 通常是比相应的 Win32 API 代码更高级别的构造(std::asyncstd::futurestd::condition_variable...)。