当 InternetOpenURL 尝试(但失败)连接时,如何避免 CPU 完全使用或终止?
我有一个相当简单的应用程序,它在线程中下载文件。此线程使用 WinINet API,并开始如下:
HINTERNET hInternet = InternetOpen(strUserAgent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD dwFlags = INTERNET_FLAG_NO_UI | INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
HINTERNET hUrl = InternetOpenUrl(hInternet, m_strURL.c_str(), L"", 0, dwFlags, NULL);
但是,如果没有互联网连接,或者远程主机已关闭,InternetOpenUrl
将需要很长时间才能超时并完成。当它执行此操作时(也就是说,仅在无法连接到远程主机的情况下),它将使用一个 CPU 的 80-100%,直到它最终返回。由于超时延迟设置,这种情况通常会持续一分钟左右。在一个系统上,尽管有超时设置(如下所述),这种情况仍会持续长达十分钟。
我该如何:
- 在尝试连接时避免如此大量的 CPU 使用?
- 如果我想关闭应用程序,请通知线程终止?通常超时是可以的,但如果应用程序需要关闭,那么它将等待该线程完成,这会花费大量 CPU 在
InternetOpenUrl
内执行很少的操作。
[旁白:InternetQueryOption 显示的我系统上的当前超时设置:
INTERNET_OPTION_CONNECT_TIMEOUT
:60 秒INTERNET_OPTION_RECEIVE_TIMEOUT
:30 秒INTERNET_OPTION_SEND_TIMEOUT
:30 秒
更改这些会减少方法放弃并返回之前的时间,因此减少了使用这么多 CPU 所花费的时间,但可能会影响连接 - 之后总之,超时是有原因的。该应用程序可用于奇怪的连接情况,例如在船上,连接可能是通过卫星进行的,延迟较高,并且比标准桌面互联网连接需要更长的时间。我不知道合理的超时是多少。此外,必须有一种更好的方法来避免 CPU 使用并比简单地缩短超时更快地终止。]
I have a fairly simple application which downloads files in a thread. This thread uses the WinINet APIs, and begins like so:
HINTERNET hInternet = InternetOpen(strUserAgent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD dwFlags = INTERNET_FLAG_NO_UI | INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
HINTERNET hUrl = InternetOpenUrl(hInternet, m_strURL.c_str(), L"", 0, dwFlags, NULL);
However, if there is no internet connection, or the remote host is down, InternetOpenUrl
will take a long time to time out and complete. While it is doing this - that is, only in the situation that it can't connect to the remote host - it will use between 80-100% of one CPU until it finally returns. This can often continue for a minute or so, because of the timeout delay setting. On one system, in spite of the timeout settings (noted below), this has continued for up to ten minutes.
How do I:
- Avoid such massive CPU usage when it's just trying to connect?
- Signal the thread to terminate if I want to shut down the app? Normally a timeout is fine, but if the app needs to close then it will wait on this thread to finish, which is spending lots of CPU doing very little inside
InternetOpenUrl
.
[Aside: Current timeout settings on my system, as revealed by InternetQueryOption:
INTERNET_OPTION_CONNECT_TIMEOUT
: 60sINTERNET_OPTION_RECEIVE_TIMEOUT
: 30sINTERNET_OPTION_SEND_TIMEOUT
: 30s
Changing these would decrease the time before the method gave up and returned and so decrease the time spent using so much CPU, but might affect connecting - after all, the timeouts are there for a reason. This app can be used in odd connection situations, such as on board ship, where connecting could potentially be over satellite with high latency and take longer than a standard desktop internet connection. I do not know what reasonable timeouts would be. Also, there has to be a better method to avoid the CPU usage and terminate more quickly than simply shortening the timeouts.]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以在异步模式下使用WinInet。不确定是否解决了 CPU 利用率问题,但可以正确处理终止。
You can use WinInet in asynchronous mode. Not sure whether it solves CPU utilization issue but termination can be handled properly.
我认为您可以使用 InternetCloseHandle 关闭从 InternetOpen 返回的会话句柄。
根据 http://msdn.microsoft.com/ en-us/library/aa384350(v=VS.85).aspx 它将取消阻止该句柄上的任何挂起操作。
因此,基本上,如果您将 InternetOpenUrl 保留在单独的线程中,您仍然可以从父线程中关闭会话句柄(如果您在异步模式下使用它,则不需要单独的线程)。您可以为任何资源清理设置状态回调函数。
如果要设置不同的超时,请使用 InternetSetOption。
PS:我使用WinINet库做任何事情已经有一段时间了,所以我不能保证上述方法一定有效。
I think you can close the session handle returned from InternetOpen with InternetCloseHandle.
According to http://msdn.microsoft.com/en-us/library/aa384350(v=VS.85).aspx it will unblock any pending operation on that handle.
So basically if you keep InternetOpenUrl in a separate thread, you can still close the session handle from the parent thread(a seperate thread is not required if you are using it in async mode). You can set a status callback function for any resource cleanup.
If you want to set a different timeout, use InternetSetOption.
PS: Its been a while I've done anything with WinINet library, so I cannot guarantee that the above method will work.