【问题标题】:Async callback call for a sync WinHTTP request同步 WinHTTP 请求的异步回调调用
【发布时间】:2015-05-03 23:36:39
【问题描述】:
我在同步模式下使用 WinHTTP,没有传递WINHTTP_FLAG_ASYNC 标志,我认为回调总是被同步调用。这确实是大多数时间发生的情况,但是有时,当调用WinHttpCloseHandle 时,不会立即使用WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 通知调用回调。相反,它会在之后从不同的线程中调用。
这是预期的行为吗?如果看到是同步的,为什么在某些情况下它会变得异步?我知道如何解决它(如果我没有立即得到它,请等待 WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 通知),但我不明白为什么会出现这种行为。
【问题讨论】:
标签:
winapi
asynchronous
winhttp
【解决方案1】:
WinHTTP 不承诺在同步模式下同步“同一线程”回调。恰恰相反,MSDN states the opposite:
回调函数必须是线程安全的和可重入的因为它可以在另一个线程上为单独的请求调用,并在当前请求的同一线程上重新进入。因此,必须对其进行编码以在处理时安全地处理重入。当dwInternetStatus参数等于WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING时,回调不需要能够处理同一个请求的重入,因为这个回调保证是最后一个,并且在处理这个请求的其他消息时不会发生。
这意味着您看到的症状基本上是设计行为,与异步模式无关:一些回调调用可能从工作线程发送给您,然后线程竞速可能会在您的回调后期到达您的代码。您需要考虑到这一点,要么忽略那些迟到的调用,要么与它们同步,要么尽早明确地重置回调,以免收到迟到的通知。
关于 WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 特别是 MSDN 解释了您可以完全依赖的内容(参见上面的引用)。