1

在 Linux 上,我将使用 fork() 创建一个子进程,这将是我的倒数计时器,一旦计时器结束,子进程将向父进程发送一个信号,告诉它计时器已经结束。然后父进程应该相应地处理信号。

我不知道如何在 Windows 上执行此操作。这里有些人建议使用线程,但他们从未编写任何示例代码来说明如何做到这一点。

最重要的是计时器是非阻塞的,这意味着它在后台保持倒计时,而程序正在接受用户的输入并正常处理它。

你能告诉我怎么做吗?

编辑:

该应用程序是一个控制台。请给我看示例代码。谢谢!

更新:

所以在我阅读了这里的一些建议之后,我在这里搜索了一些答案,发现这个很有帮助

然后我写了下面的代码,它可以工作,但不是应该的:

#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;

#define TIMER_VALUE (5 * 1000) //5 seconds = 5000 milli seconds
HANDLE g_hExitEvent = NULL;

bool doneInTime = false;
string name;

bool inputWords();


//The below function will be called when the timer ends
void CALLBACK doWhenTimerEnds(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    if(!doneInTime)
    {
        cout << "\nOut of time ... try again ..." << endl;
        name = "";
        doneInTime = inputWords();
    }
    SetEvent(g_hExitEvent);
}


bool inputWords()
{

    /* doWhenTimerEnds() will be called after time set by 5-th parameter and repeat every 6-th parameter. After time elapses,
    callback is called, executes some processing and sets event to allow exit */
    HANDLE hNewTimer = NULL; 
    BOOL IsCreated = CreateTimerQueueTimer(&hNewTimer, NULL, doWhenTimerEnds, NULL, TIMER_VALUE, 0, WT_EXECUTELONGFUNCTION);

    g_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    cout << "Input your name in 5 seconds .. " << endl;
    std::getline(cin, name);

    DeleteTimerQueueTimer(NULL, hNewTimer, NULL);
    return true;
}

int main()
{
    doneInTime = inputWords();
    cout << "Hello, " << name << "! You're done in time" << endl;

    //WaitForSingleObject(g_hExitEvent, 15000);

    system("pause");
    return 0;
}

问题是,被中断的 getline() 永远不会停止,随后的 getline() 甚至会读取之前输入的文本!请问我该如何解决?如果有更好的方法,你能指出我吗?

4

5 回答 5

5

下面是一个适用于 Windows API 的示例:

#include <windows.h>
#include <iostream>

DWORD WINAPI threadProc()
{
    for (int i = 0; ; ++i)
    {
        std::cout << i << '\n';
        Sleep (1000);
    }

    return 0;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
                    LPSTR lpszCmdLine, int iCmdShow)
{
    CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)threadProc, NULL, 0, NULL);

    int i;
    std::cin >> i;

    return ERROR_SUCCESS;
}

基本上,主函数创建一个使用该过程执行的线程threadProc。您可以将其threadProc视为线程。一旦结束,线程就结束了。

threadProc大约每秒输出一次运行计数,而 main 函数等待阻塞输入。一旦给出输入,整个事情就结束了。

另请注意,CreateThread它与最小参数一起使用。它返回一个线程句柄,您可以在函数中使用,如WaitForSingleObject,最后一个参数可以接收线程 ID。

于 2012-05-27T22:35:57.767 回答
4

您可以在线程内或线程外使用可等待计时器对象。要使用这种对象,只需使用SetWaitableTimer函数。根据 MSDN 的函数定义:

激活指定的等待计时器。当到期时间到达时,会向定时器发出信号,并且设置定时器的线程调用可选的完成例程。

于 2012-05-27T22:42:59.150 回答
1

如果您为它们实现 kbhit() 函数,这是另一个可以跨平台工作的解决方案:

#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

#if defined(WIN32)
    #include <conio.h>
#else
    // kbhit() implementation for other platforms
#endif

boost::mutex    mutex_;
bool            timeExpired_ = false;

void threadFunc()
{
    while(1) {
        {
            boost::mutex::scoped_lock lock(mutex_);
            if (timeExpired_)
                break;
            #if defined(WIN32)
                kbhit();
            #endif
        }
        boost::this_thread::sleep(boost::posix_time::milliseconds(1));
    }
}

int main(int argc, char *argv[])
{
    boost::thread worker(threadFunc);

    worker.timed_join(boost::posix_time::milliseconds(5000));

    {
        boost::mutex::scoped_lock lock(mutex_);
        timeExpired_ = true;
    }

    worker.join();

    return 0;
}

这种方法使用 boost::thread 并在创建线程后等待 5 秒来设置过期标志,然后再次等待线程,直到它完成其功能。

于 2012-05-28T21:55:52.920 回答
0

寻找相同问题的解决方案,我发现这篇文章非常有帮助:

http://www.codeproject.com/Articles/1236/Timers-Tutorial

正如您似乎已经发现的那样,最好的答案(在 Windows 2000 之后的世界中)似乎是队列计时器,即 CreateTimerQueueTimer

于 2012-10-06T01:28:42.883 回答
-2

试试这个:

//Creating Digital Watch in C++
#include<iostream>
#include<Windows.h>
using namespace std;

struct time{

int hr,min,sec;
};
int main()
{
time a;
a.hr = 0;
a.min = 0;
a.sec = 0;

for(int i = 0; i<24; i++)
{
    if(a.hr == 23)
    {
        a.hr = 0;
    }

    for(int j = 0; j<60; j++)
    {
        if(a.min == 59)
        {
            a.min = 0;
        }

        for(int k = 0; k<60; k++)
        {
            if(a.sec == 59)
            {
                a.sec = 0;
            }

            cout<<a.hr<<" : "<<a.min<<" : "<<a.sec<<endl;
            a.sec++;
            Sleep(1000);
            system("Cls");
        }
    a.min++;

}

    a.hr++;
}

}
于 2013-12-11T14:32:14.200 回答