取消 WIN32 线程池中预定的工作/io/计时器项目
我一直在研究 Windows 的(新的?)线程池 API。我一直在按照使用线程池函数 我一直在仔细研究 MSDN 上的 API。关于清理小组,我有些不明白。
调用 SetThreadpoolCallbackCleanupGroup()
时,第三个参数描述为
如果在释放关联对象之前取消清理组,则调用清理回调。当您调用
CloseThreadpoolCleanupGroupMembers()
.
如果我的理解是正确的,这意味着您可以取消挂起的工作/io/计时器项目,并要求它在每个对象上调用清理回调函数而不是原始队列工作/io/计时器项目的回调。这听起来很酷,我想使用它。
不幸的是,MSDN 上没有记录用于相关回调的 PTP_CLEANUP_GROUP_CANCEL_CALLBACK
类型,并且相关示例未使用此功能。
我将法律掌握在自己手中,追溯到 WinNT.h
的定义并发现了以下内容。
typedef VOID (NTAPI *PTP_CLEANUP_GROUP_CANCEL_CALLBACK)(
__inout_opt PVOID ObjectContext,
__inout_opt PVOID CleanupContext
);
删除这个看起来很有趣的声明中的残渣,你会得到:
typedef void ( __stdcall * PTP_CLEANUP_GROUP_CANCEL_CALLBACK )
( void* ObjectContext, void* CleanupContext );
问题:如果你必须进行有根据的猜测,你认为 ObjectContext
和 CleanupContext
参考?
我的第一个猜测是 CleanupContext
是您在启动清理时指定的内容:因此是 CloseThreadpoolCleanupGroupMembers()
的第三个参数。我非常有信心这个猜测是正确的,因为 API 调用是如此直接相关。
我的第二个猜测是 ObjectContext
是您在提交 work/io/timer 项目时指定的内容:这是 CreateThreadpoolWork()
等。我完全不确定情况是否如此。
有人可以证实这些猜测是正确的吗?以前有人用过这个功能吗?
I've been playing around with Windows' (new?) thread pool API. I've been following through with the example in the Using the Thread Pool Functions and I've been taking a good hard look at the API on MSDN. There's something I don't get about cleanup groups.
When invoking the SetThreadpoolCallbackCleanupGroup()
, the third parameter is described as
The cleanup callback to be called if the cleanup group is canceled before the associated object is released. The function is called when you call
CloseThreadpoolCleanupGroupMembers()
.
If my understanding is correct, the means that you can cancel pending work/io/timer items and ask it to invoke the cleanup callback function on each of these objects instead of the originally queue work/io/timer item's callback. This sounds cool, and I'd like to use it.
Unfortunately, the PTP_CLEANUP_GROUP_CANCEL_CALLBACK
type used for the callback in question is not documented on MSDN and the example in question does not use this feature.
Taking the law into my own hands, I've traced back the definition to WinNT.h
and found the following.
typedef VOID (NTAPI *PTP_CLEANUP_GROUP_CANCEL_CALLBACK)(
__inout_opt PVOID ObjectContext,
__inout_opt PVOID CleanupContext
);
Removing the cruft on this funny looking declaration gets you:
typedef void ( __stdcall * PTP_CLEANUP_GROUP_CANCEL_CALLBACK )
( void* ObjectContext, void* CleanupContext );
Question: If you would have to take an educated guess, what do you think ObjectContext
and CleanupContext
refer to?
My 1st guess is that CleanupContext
is what you specify at the moment you initiate cleanup: thus the 3rd parameter to CloseThreadpoolCleanupGroupMembers()
. I'm pretty confident this guess is correct because the API calls are so directly related.
My 2nd guess is that ObjectContext
is what you specify at the moment you submit the work/io/timer item: this the 2nd parameter to CreateThreadpoolWork()
et al. I'm totally unsure that this is the case.
Can someone confim that these guesses are correct? Has anyone used this feature before?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于与调用 CloseThreadpoolCleanupGroupMembers 时尚未关闭的同一回调环境关联的每个对象,都会调用您使用 SetThreadpoolCallbackCleanupGroup 函数指定的可选清理回调。回调的第一个参数(对象上下文)是您在使用 TrySubmitThreadpoolCallback、CreateThreadpoolWork 等函数时指定的 void* 参数的值。回调的第二个参数(清理上下文)是您在使用 CloseThreadpoolCleanupGroupMembers 函数时指定的 void* 参数的值。
要记住的重要一点是,是否为特定对象调用清理回调并不取决于该对象是否具有未完成的回调。仅针对尚未关闭的对象调用它。换句话说,完全有可能调用该对象的回调,然后为同一对象调用清理回调。
例如,如果您使用 CreateThreadpoolWork 函数创建一个工作对象,但在调用 CloseThreadpoolCleanupGroupMembers 之前未能调用 CloseThreadpoolWork 函数,那么即使该对象的回调已经执行,也会为该对象调用清理回调。未能调用 CloseThreadpoolWork 不是一个错误,因为 CloseThreadpoolCleanupGroupMembers 将关闭与清理组关联的任何对象。
另一个需要注意的问题是使用 TrySubmitThreadpoolCallback 函数时。这是 CreateThreadpoolWork 的更简单版本,您不必考虑创建、提交和关闭工作对象。技巧是,一旦执行了工作对象的回调,线程池就会自动关闭工作对象。这意味着只有当该对象的回调仍处于挂起状态并且您在调用 CloseThreadpoolCleanupGroupMembers 取消任何挂起的回调时指定 TRUE 时,才会为此对象调用清理回调。
The optional cleanup callback you specify using the SetThreadpoolCallbackCleanupGroup function is called for each object that is associated with the same callback environment that has not already been closed by the time CloseThreadpoolCleanupGroupMembers is called. The callback’s first parameter, the object context, is the value of the void* parameter you specify when using the TrySubmitThreadpoolCallback, CreateThreadpoolWork, etc. functions. The callback’s second parameter, the cleanup context, is the value of the void* parameter you specify when using the CloseThreadpoolCleanupGroupMembers function.
The important thing to remember is that whether the cleanup callback is called for a particular object is not dependent on whether or not that object has outstanding callbacks. It is only called for objects that have not yet been closed. In other words it’s entirely possible that the object’s callback is called and then the cleanup callback is called for that same object.
If for example you create a work object using the CreateThreadpoolWork function and fail to call the CloseThreadpoolWork function prior to calling CloseThreadpoolCleanupGroupMembers then the cleanup callback will be called for that object even if the object’s callback has already executed. Failing to call CloseThreadpoolWork is not a bug as CloseThreadpoolCleanupGroupMembers will close any objects associated with the cleanup group.
Another twist to watch out for is when using the TrySubmitThreadpoolCallback function. This is a simpler version of CreateThreadpoolWork in that you don’t have to think about creating, submitting, and closing the work object. The trick is that the thread pool with automatically close the work object once its callback has executed. This means that the cleanup callback will only be called for this object if its callback is still pending and you specify TRUE when calling CloseThreadpoolCleanupGroupMembers to cancel any pending callbacks.