В документации указано, что InternetOpen можно вызывать несколько раз без каких-либо проблем. Мой вопрос, хотя, должен я должен вызывать InternetCloseHandle на дескрипторе, возвращенном им несколько раз?WinInet и InternetOpen
Например, у меня есть класс, который я называю CAPIRequestContext
, у которого есть дескриптор, который возвращается InternetOpen. У каждого из моих запросов есть своя собственная копия. Прямо сейчас я вызываю InternetCloseHandle в деструкторе, поэтому он вызывается несколько раз.
Мне интересно, могут ли возникнуть следующие проблемы: Тема А создает CAPIRequestObject
, который вызывает InternetOpen и сохраняет дескриптор. Thread B делает то же самое, но затем выходит за рамки до того, как Thread A выйдет, поэтому Thread B вызывает деструктор в собственном CAPIRequestObject
, который вызывает InternetCloseHandle
на дескрипторе, возвращенном InternetOpen.
Должен ли я удалить вызов InternetCloseHandle в деструкторах моего класса? По крайней мере, для InternetHandle? Я предполагаю, что я должен вызвать InternetCloseHandle для дескриптора, возвращаемого HttpOpenRequest.
У меня есть аналогичные вопросы относительно ручки, возвращаемой InternetConnect. Разделяются ли эти ручки?
Вот некоторые примеры кода, минус некоторый внешний код, который я не думаю, что это связано с вопросом:
class CAPIClient;
class CAPIRequest
{
public:
CAPIRequestContext()
{
m_hConn = NULL;
m_hInternet = NULL;
m_hRequest = NULL;
}
~CAPIRequestContext()
{
if (m_hRequest) InternetCloseHandle(m_hRequest);
if (m_hConn) InternetCloseHandle(m_hConn);
if (m_hInternet) InternetCloseHandle(m_hInternet);
}
bool Init(const CAPIClient &client, const std::string &uri, const std::string &method)
{
ATLASSERT(!(m_hInternet || m_hConn || m_hRequest));
if (m_hInternet || m_hConn || m_hRequest) throw std::exception("Cannot init request more than once.");
bool success = false;
m_AuthToken = *client.m_pAuthToken;
URI = uri;
m_hInternet = InternetOpen("MyApp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD requestTimeout = 60 * 1000; // Set timeout to 60 seconds instead of 30
if (m_hInternet)
{
InternetSetOption(m_hInternet, INTERNET_OPTION_RECEIVE_TIMEOUT, &requestTimeout, sizeof(requestTimeout));
m_hConn = InternetConnect(m_hInternet, (LPSTR)client.m_host.c_str(), client.m_port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)this);
if (m_hConn) {
m_hRequest = HttpOpenRequest(m_hConn, method.c_str(), uri.c_str(), "HTTP/1.1", NULL, NULL, client.GetOpenRequestFlags(), 0);
}
if (m_hRequest)
{
success = true;
}
}
return success;
}
}
// There are additional calls like
// SendRequest
// GetData
// GetFullResponse
private:
// Added these methods to make sure I'm not copying the handles
enter code here
CAPIRequestContext(const CAPIRequestContext &other) = delete;
CAPIRequestContext& operator=(const CAPIRequestContext& other) = delete;
private:
HINTERNET m_hInternet;
HINTERNET m_hConn;
HINTERNET m_hRequest;
}
Каждый InternetOpen() должен быть точно сопряжен с InternetCloseHandle(), который передает дескриптор, полученный от открытого вызова.Не могу предположить, что ваш код еще этого не делает. Почувствуйте это, используя assert() для возвращаемого значения. –