std::thread 在 C++ 中未执行函数。

huangapple go评论79阅读模式
英文:

std::thread dosnt dosnt excute funtion c++

问题

这是您提供的代码的翻译部分:

我有这个简单的函数:

class Timer {
    std::atomic<bool> active{true};

public:

    void setInterval(auto function, int interval);
    void stop();

};


void Timer::setInterval(auto function, int interval) {
    active = true;
    std::thread t([=]() {
        while(active.load()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
            if(!active.load()) return;
            function();
        }
    });
    t.detach();
}

void Timer::stop() {
    active = false;
}

现在当我尝试运行它:

int main()
{
    printf("start\n");
    Timer* timer = new Timer();
    timer->setInterval([&]() {
        std::cout << "hello" << std::endl;
    }, 1000);
    return 0;
};

仅从主类中打印开始,它从未到达setInterval函数内的function(); 它只是停止了应用程序,没有错误。

编译/链接命令:

/usr/bin/g++ -fdiagnostics-color=always -std=c++14 -pthread -g /home/vagrant/cpp/batch/main.cpp -o /home/vagrant/cpp/batch/main
英文:

i have this simple function :

class Timer {
	std::atomic&lt;bool&gt; active{true};
	
    public:
         
        void setInterval(auto function, int interval);
        void stop();

};


void Timer::setInterval(auto function, int interval) {
    active = true;
    std::thread t([=]() {
        while(active.load()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
            if(!active.load()) return;
            function();
        }
    });
    t.detach();
}

void Timer::stop() {
    active = false;
}

Now when i try to run it :

int main()
{
    printf(&quot;start\n&quot;);
    Timer* timer = new Timer();
    timer-&gt;setInterval([&amp;]() {
        std::cout &lt;&lt; &quot;hello&quot; &lt;&lt; std::endl;
    },1000); 
    return 0;
};

Only the start printed from the main class , its never reach the function(); inside the
setInterval function its just stops the app with no error .

the compile/link command :

/usr/bin/g++ -fdiagnostics-color=always -std=c++14 -pthread -g /home/vagrant/cpp/batch/main.cpp -o /home/vagrant/cpp/batch/main

答案1

得分: 2

这是正确使用线程对象来运行计时器的众多方法之一。

#include <atomic>
#include <thread>
#include <chrono>
#include <iostream>

class Timer {
  private:
    std::atomic<bool> active = false;
    std::unique_ptr<std::thread> timer_thread;

  public:
    // 这个类需要一个析构函数。
    ~Timer()
    {
        stop();
    }

    // 这个函数名字有误导性,
    // void setInterval(auto function, int interval);
    //
    // 让我们将其重命名为它实际做的事情,还要尽量将函数参数放在最后,
    // 这样在使用lambda表达式调用时,代码更易读。
    //
    // 你不知道 'cb',调用者的可调用对象是可复制还是可移动的,所以应该使用完美
    // 转发,这仅在模板中( readily)可用。
    
    template <typename Fn>
    void start(int interval, Fn&& cb)
    {
         stop();  // 确保我们停止了。
         active = true;

         // 启动线程,回调对象的 forward<> 是重要的!
         timer_thread = std::make_unique<std::thread>(
             [this, ms = std::chrono::milliseconds(interval), cb = std::forward<Fn>(cb)]() {
                while (active) // 调用 atomic<>::load() 自动完成
                {
                    std::this_thread::sleep_for(ms);
                    if (active)
                        cb();
                }
            });
    }

    // 这是我们终止线程并等待它退出的地方。
    void stop()
    {
        active = false;
        if (timer_thread)
        {
            timer_thread->join();
            timer_thread.reset();
        }
    }

    bool isRunning() const 
    {
        return active;
    }
};

int main()
{
    std::cout << "start\n";

    Timer timer;  // 绝对没有必要将计时器放在堆上。
    int n = 4;    // 一个简单的倒计时示例,直到1。

    timer.start(1000, [&]() { 
         std::cout << "countdown: " << n << '\n';
         if (--n <= 0) 
             timer.stop(); 
     });

    // 在退出程序之前,我们应该等待计时器停止。
    while (timer.isRunning()) {}

    return 0;
};

请注意,上述代码是使用C++编写的,用于创建一个简单的计时器。如果您需要进一步的解释或有其他问题,请随时提出。

英文:

Here is one of the many ways of correctlty using a thread object to run your timer.

#include &lt;atomic&gt;
#include &lt;thread&gt;
#include &lt;chrono&gt;
#include &lt;iostream&gt;
class Timer {
private:
std::atomic&lt;bool&gt; active = false;
std::unique_ptr&lt;std::thread&gt; timer_thread;
public:
// this class needs a destructor.
~Timer()
{
stop();
}
// this function name is misleading, 
// void setInterval(auto function, int interval);
//
// let&#39;s rename it to what it does, also try to keep 
// the function argument last, this makes the code
// more legible when calling with a lambda.
//
// you do not know if &#39;cb&#39;, the caller&#39;s callable object
// is copyable or moveable, so you should use perfect 
// forwarding, that&#39;s only (readily) available from a 
// template.
template &lt;typename Fn&gt;
void start(int interval, Fn&amp;&amp; cb)
{
stop();  // make sure we&#39;re stopped.
active = true;
// start the thread, the forward&lt;&gt; of the callback object is 
// important!
timer_thread = std::make_unique&lt;std::thread&gt;(
[this, ms = std::chrono::milliseconds(interval), cb = std::forward&lt;Fn&gt;(cb)]() {
while (active) // calls atomic&lt;&gt;::load() automatically
{
std::this_thread::sleep_for(ms);
if (active)
cb();
}
});
}
// this is where we kill the thread, and wait for it to exit.
void stop()
{
active = false;
if (timer_thread)
{
timer_thread-&gt;join();
timer_thread.reset();
}
}
bool isRunning() const 
{
return active;
}
};
int main()
{
std::cout &lt;&lt; &quot;start\n&quot;;
Timer timer;  // There&#39;s absolutely no need to place timer on the heap.
int n = 4;    // simple countdown to 1 for example.
timer.start(1000, [&amp;]() { 
std::cout &lt;&lt; &quot;countdown: &quot; &lt;&lt; n &lt;&lt; &#39;\n&#39;;
if (--n &lt;= 0) 
timer.stop(); 
});
// We should wait for the timer to stop, before exiting the program.
while (timer.isRunning()) {}
return 0;
};

huangapple
  • 本文由 发表于 2023年1月9日 19:15:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75056477.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定