0

我不是经验丰富的 C++ 程序员。所以我只想知道如何像java在C++中那样实现定时器和定时器任务。我已经尝试timer_create了 timer_create 手册页中的示例,但它没有按照我的要求工作。我希望在特定时间跨度之后触发事件,如果满足特定条件,则应取消计时器。

任何帮助将不胜感激。谢谢,尤维。

4

2 回答 2

3

我也在寻找类似 TimerTask 的 Java,但是当我遇到这个问题时,我需要一个用于 Windows C++ 的 Java。经过一天的主要研究 SO 和学习传递类成员函数后,我能够整理出一个似乎对我很有效的解决方案。我意识到我回答这个问题已经晚了好几年,但也许仍在寻找这个解决方案的人会发现这很有用。

这是一个仅限 Windows 的解决方案,我使用 Visual Studio C++ 在 Windows 10 上进行了测试。我还在学习 C++,所以如果我违反了任何规则,请保持温和。我意识到例外是基本的,但它们很容易根据您的需要进行定制。我创建了一个类似于 Java 类的 TimerTask 类。您需要从 TimerTask 类派生一个新的用户类,并创建一个“任务”函数,其中包含您希望定期执行的代码。这是 TimerTask 类:

--TimerTask.h--
#pragma once
#include <thread>

class TimerTask {
    HANDLE timeoutEvent;
    DWORD msTimeout;
    bool exit = false;
    void* pObj;

    static void taskWrapper(TimerTask* pObj) {
        while (!pObj->exit) {
            DWORD waitResult = WaitForSingleObject(pObj->timeoutEvent, pObj->msTimeout);
            if (pObj->exit)
                break;
            pObj->task();
        }
    }

public:

    TimerTask::TimerTask() {
        timeoutEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!timeoutEvent) {
            throw "TimerTask CreateEvent Error: ";
        }
    }

    TimerTask::~TimerTask() {
        CloseHandle(timeoutEvent);
    }

    // Derived class must create task function that runs at every timer interval.
    virtual void task() = 0;

    void start(void* pObj, DWORD msTimeout) {
        this->pObj = pObj;
        this->msTimeout = msTimeout;

        std::thread timerThread(taskWrapper, (TimerTask*)pObj);
        timerThread.detach();
    }

    void stop() {
        exit = true;
        if (!SetEvent(timeoutEvent))
            throw "TimerTask:stop(): Error: ";
    }
};

这是一个使用示例。为简洁起见,我没有包括错误检查。

--Test.cpp--
#include "Windows.h"
#include <iostream>
#include "TimerTask.h"

using namespace std;

class KeepAliveTask : public TimerTask {
public:
    void task() {
        cout << "Insert your code here!\n";
    }
};

int main()
{
    cout << "Hello, TimerTask!\n";

    KeepAliveTask keepAlive;
    keepAlive.start(&keepAlive, 1000);  // Execute once per second

    Sleep(5100);    // Pause 5.1s to give time for task thread to run.
    keepAlive.stop();
    Sleep(1000);    // Pause another sec to give time for thread to stop.

    return 0;
}
于 2018-03-03T16:05:00.140 回答
2

这通常是一个非常困难的问题,因为您本质上要求一些并发处理,或者至少是异步处理。

最简单的单线程解决方案是使用类似 Posix 的alarm(2). 这将导致在指定时间后向您的进程发送信号。您需要注册一个信号处理程序(例如使用signal(2)),但您会受到它的所有限制(例如您只能在处理程序中调用异步安全函数)。

第二个单线程选项是使用select-style(或epoll-style)I/O 循环并使用内核计时器文件描述符。不过,这是最新的 Linux 功能,因此可用性会有所不同。

最后,典型的通用解决方案是使用多个线程:为计时器创建一个专用线程,其唯一目的是在设定的时间跨度内休眠,然后执行一些代码。为此,您将不得不承担并发编程职责的全部重量,例如处理共享数据、保证不存在竞争等。

一旦您决定走多线程路线,一些更高级别的库(如 Boost.ASIO 和新标准库)会提供一些不错的计时机制。

于 2012-04-06T11:21:29.610 回答