所以我有打印功能,我想在5秒内执行。问题是我想要函数中的其他所有东西。所以例如,如果我的代码是:
// insert code here...
printf("(5 seconds later) Hello"); /* should be executed in 5 seconds */
printf("heya");
以主要功能为例。现在这里是棘手的部分。虽然第一行应该在5秒内执行,但第二行应该像正常情况一样执行,如果第一行根本不存在的话。所以输出将是:
heya
(5 seconds later) Hello
如果您熟悉Cocoa或Cocoa Touch,这正是NSTimer类的工作原理。使用C ++,除了使用线程之外,还有更简单或内置的方法吗?如果没有,我将如何使用多线程进行此操作?
答案 0 :(得分:4)
使用<chrono>
和<thread>
,您可以创建一个非常简单但又简单的基础:
std::thread printLater{[] {
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("(5 seconds later) Hello");
}};
printf("heya");
printLater.join(); //when you want to wait for the thread to complete
Pubby指出的另一种方法是使用std::async
:
auto f = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("(5 seconds later) Hello");
});
printf("heya");
将std::async
存储到变量中的结果意味着调用将启动一个新线程来运行该函数。如果不存储结果,则不会有新线程。这是该语言中的新问题之一。
请注意,打印时可能不会恰好五秒钟,并且输出没有同步,因此您可能会得到交错输出块(printf
是原子的,因此每次调用的整个输出都会交错)如果在每个线程中打印的不仅仅是一件事。如果没有同步,则无法保证何时发生语句,因此如果您确实需要了解可能出现的同步问题,请务必小心。出于基本目的,这应该可行。
答案 1 :(得分:1)
以下是我解决这个问题的方法:
#include <iostream>
#include <thread>
#include <chrono>
std::thread timerThread;
void printStatement() {
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("(5 seconds later) Hello");
}
bool myBool() {
timerThread = std::thread(printStatement);
return YES;
}
int main(int argc, const char * argv[])
{
// insert code here...
printf("%i\n", myBool());
printf("heya\n");
// you could also use the async stuff, join or std::future instead of sleep()
sleep(5); // this is only here to keep the thread from being detatched before it can even finish sleeping
timerThread.detach();
return 0;
}
答案 2 :(得分:0)
我的快照版本有boost asio和std :: async。没有睡觉。
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/noncopyable.hpp>
#include <chrono>
#include <future>
#include <memory>
#include <iostream>
class MonotonicExecutor
: public boost::noncopyable,
public std::enable_shared_from_this<MonotonicExecutor> {
typedef std::function<void()> Functor;
public:
MonotonicExecutor(boost::posix_time::time_duration trig)
: m_service(),
m_serviceWork(
std::make_shared<boost::asio::io_service::work>(m_service)),
m_deadlineTimer(m_service), m_trigger(trig) {
auto fut = std::async(std::launch::async, [&]() { m_service.run(); });
fut.wait_for(std::chrono::milliseconds(1));
}
void executeAsync(Functor fun) {
m_deadlineTimer.expires_from_now(m_trigger);
m_deadlineTimer.async_wait(std::bind(&MonotonicExecutor::execute,
shared_from_this(),
std::placeholders::_1, fun));
}
void abort() { m_deadlineTimer.cancel(); }
private:
void execute(const boost::system::error_code &err, Functor fun) {
if (err != boost::asio::error::operation_aborted &&
m_deadlineTimer.expires_at() <=
boost::asio::deadline_timer::traits_type::now()) {
m_deadlineTimer.cancel();
fun();
m_deadlineTimer.expires_from_now(m_trigger);
m_deadlineTimer.async_wait(std::bind(&MonotonicExecutor::execute,
shared_from_this(),
std::placeholders::_1, fun));
}
}
private:
boost::asio::io_service m_service;
std::shared_ptr<boost::asio::io_service::work> m_serviceWork;
boost::asio::deadline_timer m_deadlineTimer;
boost::posix_time::time_duration m_trigger;
};
int main(int argc, char *argv[]) {
auto executor =
std::make_shared<MonotonicExecutor>(boost::posix_time::seconds(3));
executor->executeAsync([&]() {
std::cout << boost::posix_time::to_iso_string(
boost::posix_time::second_clock::local_time())
<< std::endl;
});
auto stop = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
executor->abort();
std::cout << "Wait and see if the task is aborted" << std::endl;
stop = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}