积极答复者
关于WaitForThreadpoolTimerCallbacks函数

问题
-
VOID CALLBACK TimeoutCallback( PTP_CALLBACK_INSTANCE pInstance,PVOID pvContext, PTP_TIMER pTimer) { int i=0; while(1){ cout<<++i<<endl; Sleep(3000); } } int _tmain(int argc, _TCHAR* argv[]) { PTP_TIMER lpTimer = CreateThreadpoolTimer(TimeoutCallback, NULL, NULL); ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG) -(10000000); FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer(lpTimer, &ftRelativeStartTime, 5000, 0); Sleep(2000); WaitForThreadpoolTimerCallbacks(lpTimer,TRUE); cout<<"取消"<<endl // CloseThreadpoolTimer(lpTimer); system("pause"); return 0; }
我实在没找到哪个子版块适合这个帖子。
请问,在我调用完WaitForThreadpoolTimerCallbacks(lpTimer,TRUE);之后,应该只有之前已经开启的线程在运行,不会再新开启线程去执行回调函数啊。但是事实上怎么还会不断由定时器开启新的线程呢?这个函数不起作用吗?
谢谢。
答案
-
赤口白舌,你好
我想关于WaitForThreadpoolTimerCallbacks函数的使用,这里还有一些表述不清的地方。引用一下MSDN的文档
如果传递TRUE给参数bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将试图取消这个先前提交的工作项。如果这个工作项正在被处理,那么这个处理不会被打断,该函数会等待直到工作项结束才返回。如果这个工作项被提交,但是目前不在处理,那么该函数就会立即取消该工作项并理解返回,那么这个工作项的异步函数就不会被调用了。
如果传递FALSE给传递bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将挂起这个调用它的线程,直到指定的工作项完成,而线程池中执行这个工作项的线程在完成处理工作项之后返回线程池,继续处理下一个工作项。
诚然,当我们设置该函数第二个参数为TRUE时,当前工作项理应被cancel掉。但需要注意的是,在你的示例程序里,该函数并未并执行。这归结于它的执行细节。WaitForThreadpoolTimerCallbacks函数只等待加入队列的工作项,或者正在执行中的工作项。你计时器回调函数里,只是简单的输出了一串字符到终端,这可以说是几乎不耗时的。我们可以试着来简单改一下代码,
// WaitforDemo.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <Windows.h> using namespace std; VOID CALLBACK TimeoutCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PTP_TIMER pTimer ) { SleepEx(1000, false); cout<<"test"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { PTP_TIMER lpTimer = CreateThreadpoolTimer(TimeoutCallback, NULL, NULL); ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG) -(10000000); //5秒中之后首次执行让WaitFor函数有足够的时间取消工作项<br/> FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer(lpTimer, &ftRelativeStartTime, 3000, 0); SleepEx(10000, false); WaitForThreadpoolTimerCallbacks(lpTimer,TRUE); //第二个参数为true,表示我希望取消工作项 CloseThreadpoolTimer(lpTimer); cout<<"取消"<<endl; system("pause"); return 0; }
我们在回调函数中,加入了一个Sleep,以模拟现实中的耗时操作(或者说达到工作项正在执行中的目的)。运行程序,我们会发现,test字符串将被输出3次后,程序结束。而如果我们将第二个参数改为FALSE,结果会变为,test字符串将被输出4次后,程序结束。在以上代码中最后一次工作项由于正在执行,被WaitForThreadpoolTimerCallbacks取消。
希望这对您能有所帮助,如果仍然有任何疑问,请让我知道。
致,
Yves Zhang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已编辑 Yves.Z 2011年4月6日 7:54 修改格式
- 已建议为答案 Yves.Z 2011年4月6日 7:56
- 已标记为答案 SplendourGModerator 2011年4月7日 1:55
全部回复
-
谢谢您解答
那么关于第二个参数Indicates whether to cancel queued callbacks that have not yet started to execute.怎么解释呢。windows核心编程也有说:call WaitForThreadpoolTimerCallbacks with TRUE as the last parameter to tell the thread pool that no more work items should be processed for this timer.是我哪的理解问题吗?谢谢!
-
赤口白舌,
您好!函数原型如下:
VOID WINAPI WaitForThreadpoolTimerCallbacks(
__inout PTP_TIMER pti,
__in BOOL fCancelPendingCallbacks
);
如果传递TRUE给参数bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将试图取消这个先前提交的工作项。如果这个工作项正在被处理,那么这个处理不会被打断,该函数会等待直到工作项结束才返回。如果这个工作项被提交,但是目前不在处理,那么该函数就会立即取消该工作项并理解返回,那么这个工作项的异步函数就不会被调用了。
如果传递FALSE给传递bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将挂起这个调用它的线程,直到指定的工作项完成,而线程池中执行这个工作项的线程在完成处理工作项之后返回线程池,继续处理下一个工作项。
如果您的问题解决了,请把有用的回答标记为答案.
谢谢,
Lucy
Lucy Liu [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已建议为答案 VisualElevenModerator 2011年4月1日 3:32
- 取消建议作为答案 mico_mico 2011年4月1日 6:43
-
您好,感谢您的答复和MSDN文档中所述一致,可能是我的线程函数里的循环让问题变得模糊化,我修改了下
#include <iostream> #include <Windows.h> using namespace std; VOID CALLBACK TimeoutCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PTP_TIMER pTimer ) { cout<<"test"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { PTP_TIMER lpTimer = CreateThreadpoolTimer(TimeoutCallback, NULL, NULL); ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG) -(50000000); //5秒中之后首次执行让WaitFor函数有足够的时间取消工作项<br/> FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer(lpTimer, &ftRelativeStartTime, 3000, 0); WaitForThreadpoolTimerCallbacks(lpTimer,TRUE); //第二个参数为true,表示我希望取消工作项 cout<<"取消"<<endl system("pause"); return 0;
如果按照我上面的代码理想的结果应该是“test”串一次都不输出,因为WaitForThreadpoolTimerCallbacks第二参数我已经指定TRUE了,并且执行该函数时工作项还没被处理(5秒后首次执行)。但是结果中你可以看出每3秒会输出一个test说明,工作项并没有被取消掉。 您可能会说SetThreadpoolTimer之后工作项就相当于被处理状态,而不是仅仅在执行线程函数时才算被处理状态,因此无法取消。 那么好,WaitForThreadpoolTimerCallbacks(lpTimer,FALSE);设置成false参数您再执行下看看,现在工作项工作项如果是被处理状态,起码说main函数所在线程会挂起等待工作项被处理完,下面那句“取消”是不会被输出的,但是结果是“取消”依然最先被输出,而且每三秒一次“test”。所以我觉得这个函数怎么说都说不通。 望您指教,再次感谢!!
-
赤口白舌,你好
我想关于WaitForThreadpoolTimerCallbacks函数的使用,这里还有一些表述不清的地方。引用一下MSDN的文档
如果传递TRUE给参数bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将试图取消这个先前提交的工作项。如果这个工作项正在被处理,那么这个处理不会被打断,该函数会等待直到工作项结束才返回。如果这个工作项被提交,但是目前不在处理,那么该函数就会立即取消该工作项并理解返回,那么这个工作项的异步函数就不会被调用了。
如果传递FALSE给传递bCancelPendingCallbacks,WaitForThreadpoolWorkCallbacks函数将挂起这个调用它的线程,直到指定的工作项完成,而线程池中执行这个工作项的线程在完成处理工作项之后返回线程池,继续处理下一个工作项。
诚然,当我们设置该函数第二个参数为TRUE时,当前工作项理应被cancel掉。但需要注意的是,在你的示例程序里,该函数并未并执行。这归结于它的执行细节。WaitForThreadpoolTimerCallbacks函数只等待加入队列的工作项,或者正在执行中的工作项。你计时器回调函数里,只是简单的输出了一串字符到终端,这可以说是几乎不耗时的。我们可以试着来简单改一下代码,
// WaitforDemo.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <Windows.h> using namespace std; VOID CALLBACK TimeoutCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PTP_TIMER pTimer ) { SleepEx(1000, false); cout<<"test"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { PTP_TIMER lpTimer = CreateThreadpoolTimer(TimeoutCallback, NULL, NULL); ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG) -(10000000); //5秒中之后首次执行让WaitFor函数有足够的时间取消工作项<br/> FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer(lpTimer, &ftRelativeStartTime, 3000, 0); SleepEx(10000, false); WaitForThreadpoolTimerCallbacks(lpTimer,TRUE); //第二个参数为true,表示我希望取消工作项 CloseThreadpoolTimer(lpTimer); cout<<"取消"<<endl; system("pause"); return 0; }
我们在回调函数中,加入了一个Sleep,以模拟现实中的耗时操作(或者说达到工作项正在执行中的目的)。运行程序,我们会发现,test字符串将被输出3次后,程序结束。而如果我们将第二个参数改为FALSE,结果会变为,test字符串将被输出4次后,程序结束。在以上代码中最后一次工作项由于正在执行,被WaitForThreadpoolTimerCallbacks取消。
希望这对您能有所帮助,如果仍然有任何疑问,请让我知道。
致,
Yves Zhang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已编辑 Yves.Z 2011年4月6日 7:54 修改格式
- 已建议为答案 Yves.Z 2011年4月6日 7:56
- 已标记为答案 SplendourGModerator 2011年4月7日 1:55