1

Linux では、カウントダウン タイマーとなる fork() を使用して子プロセスを作成します。タイマーが終了すると、子プロセスは親プロセスにシグナルを送信して、タイマーが終了したことを伝えます。親プロセスは、それに応じてシグナルを処理する必要があります。

Windowsでこれを行う方法がわかりません。ここでスレッドの使用を推奨する人もいますが、その方法を示すサンプル コードを書いたことはありません。

最も重要なことは、タイマーが非ブロッキングであることです。つまり、プログラムがユーザーからの入力を受け入れて通常どおり処理している間、タイマーはバックグラウンドでカウントダウンを続けます。

方法を教えてください。

編集:

アプリケーションはコンソール 1 です。そしてサンプルコードを見せてください。ありがとう!

アップデート:

ここでいくつかの提案を読んだ後、ここでいくつかの回答を検索し、これが役に立ちました。

次に、以下のコードを書きました。これは機能しますが、想定どおりではありません。

#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;
}

基本的に、メイン関数はプロシージャを使用して実行するスレッドを作成しますthreadProcthreadProcスレッドと考えることができます。それが終わると、スレッドは終了します。

threadProcメイン関数がブロッキング入力を待機している間、約 1 秒ごとに実行中のカウントを出力するだけです。入力が与えられると、すべてが終了します。

CreateThreadが最小限の引数で使用されていることにも注意してください。のような関数で使用できるスレッドへのハンドルを返し、WaitForSingleObject最後の引数はスレッド ID を受け取ることができます。

于 2012-05-27T22:35:57.767 に答える
4

Waitable Timer オブジェクトは、スレッドの内外で使用できます。そのような種類のオブジェクトを使用するには、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のような Queue Timers のようです。

于 2012-10-06T01:28:42.883 に答える