Reputation: 37
I have written the following program which It should print something for 10th time. I wanted to use timer and thread pool to implement the following program but this program only show one message and then program will quit.
#include <windows.h>
#include <process.h>
#include <iostream>
// How many seconds we'll display the message box
int g_nSecLeft = 10;
PTP_WORK g_WorkItem = NULL;
VOID CALLBACK WorkerOne(PTP_CALLBACK_INSTANCE arg_instance, PVOID arg_context, PTP_TIMER arg_timer)
{
std::printf("You have %d seconds to respond", --g_nSecLeft);
}
int main(int argc, char* argv[])
{
// Create the thread pool timer object
PTP_TIMER pointer_timer = CreateThreadpoolTimer(WorkerOne, NULL, NULL);
if (pointer_timer == NULL)
{
std::cout << "Error: something goes wrong." << std::endl;
return -1;
}
// Start the timer in one second to trigger every 1 second
ULARGE_INTEGER relative_start_time;
relative_start_time.QuadPart = (LONGLONG)-(10000000); // start in 1 second
FILETIME ft_relative_start_time;
ft_relative_start_time.dwHighDateTime = relative_start_time.HighPart;
ft_relative_start_time.dwLowDateTime = relative_start_time.LowPart;
SetThreadpoolTimer(pointer_timer, &ft_relative_start_time, 1000, 0);
if (IsThreadpoolTimerSet(pointer_timer))
{
std::cout << "Time has been set." << std::endl;
}
WaitForThreadpoolWorkCallbacks(g_WorkItem, FALSE);
return 0;
}
Why it doesn't call the callback function for more than one time?
Upvotes: 1
Views: 756
Reputation: 25398
Calling WaitForThreadpoolWorkCallbacks()
is the wrong thing to do. It waits for work items queued via CreateThreadpoolWork()
to complete, but you're not queuing any work items, so WaitForThreadpoolWorkCallbacks()
returns immediately and your program just exits.
Since you've got nothing better to do, you might as well just call Sleep()
in the main thread. Or, you can have the main thread create an event object with CreateEvent()
, then signal that event in your timer callback, and have the main thread wait for the event to be signaled.
Upvotes: 1
Reputation: 33784
you can use for instance next code
struct TimerData
{
HANDLE hEvent = CreateEvent(0, 0, 0, 0);
LONG n;
~TimerData()
{
if (hEvent) CloseHandle(hEvent);
}
TimerData(ULONG n) : n(n) {}
static VOID CALLBACK TimerCallback(
__inout PTP_CALLBACK_INSTANCE /*Instance*/,
__inout_opt PVOID Context,
__inout PTP_TIMER Timer
)
{
DbgPrint("TimerCallback(%d)\n", reinterpret_cast<TimerData*>(Context)->n);
if (!InterlockedDecrementNoFence(&reinterpret_cast<TimerData*>(Context)->n))
{
SetThreadpoolTimer(Timer, 0, 0, 0);
SetEvent(reinterpret_cast<TimerData*>(Context)->hEvent);
}
}
};
void TimerDemo(ULONG n)
{
if (TimerData* p = new TimerData(n))
{
if (p->hEvent)
{
if (PTP_TIMER Timer = CreateThreadpoolTimer(TimerData::TimerCallback, p, 0))
{
LARGE_INTEGER li = { (ULONG)-10000000, -1};
SetThreadpoolTimer(Timer, (PFILETIME)&li, 1000, 0);
WaitForSingleObject(p->hEvent, INFINITE);
CloseThreadpoolTimer(Timer);
}
}
delete p;
}
}
Upvotes: 1