我希望线程中的while循环运行,等待一秒钟,然后再次运行,依此类推,但这似乎不起作用,我该如何解决?
main(){
bool flag = true;
pthread = CreateThread(NULL, 0, ThreadFun, this, 0, &ThreadIP);
}
ThreadFun(){
while(flag == true)
WaitForSingleObject(pthread,1000);
}
我希望线程中的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 返回一个可以将信息发送回起始线程的未来。即使此示例中未使用该功能)。
#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
如果没有适当的同步,就不能保证编译器会从内存而不是缓存或寄存器中读取值。
从 UI 线程中使用Sleep
或类似的功能也将是可疑的。
对于控制台应用程序,如果您的应用程序的目的确实是在给定的持续时间内工作,您可以在主线程中等待一段时间。但通常,您可能希望等到处理完成。在大多数情况下,您通常应该等待已启动的线程已经完成。
函数的另一个问题Sleep
是,即使无事可做,线程也总是必须每隔几秒唤醒一次。如果您想优化电池使用,这可能会很糟糕。但是,另一方面,如果您的代码中有一些错误,则等待某个信号(句柄)的函数具有相对较长的超时时间可能会使您的代码更健壮地防止错过唤醒。
在某些情况下,您还需要延迟,因为您实际上没有任何等待,但您需要定期提取一些数据。
大超时也可以用作一种看门狗计时器。例如,如果您希望有事可做并且在很长一段时间内什么都没有收到,您可以以某种方式报告警告,以便用户可以检查某些事情是否无法正常工作。
我强烈建议您在编写多线程代码之前阅读一本关于多线程的书,例如Concurrency in Action 。
如果没有正确理解多线程,几乎 100% 肯定任何代码都会被窃听。您需要正确理解 C++ 内存模型 ( https://en.cppreference.com/w/cpp/language/memory_model ) 才能编写正确的代码。
等待自己的线程没有意义。当您等待一个线程时,您正在等待它已经终止,显然如果它已经终止,那么它就不能执行您的代码。您的主线程应该等待后台线程终止。
我通常还建议在 API 上使用 C++ 线程函数,因为它们:
std::async
, std::future
, std::condition_variable
...)。