Как избежать полной загрузки ЦП или прекратить работу, пока InternetOpenURL пытается (и не может) подключиться?

У меня есть довольно простое приложение, которое загружает файлы в потоке. Этот поток использует API WinINet и начинается следующим образом:

    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займет много времени, чтобы закончить и закончить. Пока он делает это - то есть, только в том случае, если он не может подключиться к удаленному хосту - он будет использовать от 80 до 100% одного ЦП, пока он, наконец, не вернется. Это часто может продолжаться в течение минуты или около того, из-за установки времени ожидания. В одной системе, несмотря на настройки тайм-аута (отмеченные ниже), это продолжалось до десяти минут.

Как я:

  • Избегать такого массового использования процессора, когда он просто пытается подключиться?
  • Сигнализировать поток, чтобы прекратить, если я хочу закрыть приложение? Обычно время ожидания хорошее, но если приложение должно закрыться, оно будет ждать завершения этого потока, который тратит много ресурсов ЦП, делая очень мало внутри InternetOpenUrl,

[В сторону: текущие настройки тайм-аута в моей системе, как показано InternetQueryOption:

  • INTERNET_OPTION_CONNECT_TIMEOUT: 60-е
  • INTERNET_OPTION_RECEIVE_TIMEOUT: 30 с
  • INTERNET_OPTION_SEND_TIMEOUT: 30 с

Их изменение уменьшит время до того, как метод завершит работу и вернется, и, следовательно, сократит время, затрачиваемое на использование столь большого количества ЦП, но может повлиять на подключение - в конце концов, таймауты существуют по причине. Это приложение может использоваться в нечетных ситуациях подключения, например, на борту судна, где подключение может потенциально осуществляться через спутник с высокой задержкой и занимать больше времени, чем стандартное подключение к Интернету на рабочем столе. Я не знаю, какие будут разумные тайм-ауты. Кроме того, должен быть лучший способ избежать использования ЦП и завершаться быстрее, чем просто сокращение тайм-аутов.]

2 ответа

Решение

Вы можете использовать WinInet в асинхронном режиме. Не уверен, решает ли это проблему использования ЦП, но завершение может быть обработано должным образом.

Я думаю, что вы можете закрыть дескриптор сеанса, возвращенный из InternetOpen с InternetCloseHandle.

Согласно http://msdn.microsoft.com/en-us/library/aa384350(v=VS.85).aspx он разблокирует все ожидающие операции с этим дескриптором.

Таким образом, если вы храните InternetOpenUrl в отдельном потоке, вы все равно можете закрыть дескриптор сеанса из родительского потока (отдельный поток не требуется, если вы используете его в асинхронном режиме). Вы можете установить функцию обратного вызова состояния для любой очистки ресурса.

Если вы хотите установить другое время ожидания, используйте InternetSetOption.

PS: я уже давно что-то делал с библиотекой WinINet, поэтому я не могу гарантировать, что вышеуказанный метод будет работать.

Другие вопросы по тегам