0

所以我有我想在 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++,除了使用线程之外,还有更简单或内置的方式吗?如果没有,我将如何使用多线程来执行此操作?

4

3 回答 3

4

使用<chrono>and <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意味着调用将启动一个新线程来运行该函数。如果不存储结果,则没有新线程。这是该语言中的新问题之一。

请注意,打印时可能不会恰好在 5 秒后,并且没有同步输出,因此printf如果打印不止一个,您可能会得到交错的输出块(是原子的,因此每个调用的整个输出都会交错)每个线程中的东西。如果没有同步,则无法保证哪些语句何时发生,因此如果您确实需要注意可能出现的同步问题,则应小心。不过,出于基本目的,这应该可以工作。

于 2013-04-03T01:49:14.813 回答
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;
}
于 2013-04-03T02:17:28.067 回答
0

我的带有 boost asio 和 std::async 的 snap 版本。没有使用睡眠。

#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;
}
于 2014-11-20T09:35:11.910 回答