PDA

Просмотр полной версии : подвисает wininet


Satell
24.08.2007, 10:58
вот есть такой код получающий страницы по winnet,
зачастую после вывода строки HttpOpenRequest Successfull перед функцией HttpSendRequest программа подвисает на несколько минут, либо очень надолго, можно ли сделать какой-нибудь таймаут для этих ф-й или как можно получать страницу с таймаутом?


char* getpage(char* userag,char* proxy, char* url, char* document, char* referer)
{
char szData[1500];
DWORD dwBytesRead;

HINTERNET hInternet = ::InternetOpen(userag, INTERNET_OPEN_TYPE_PROXY, proxy,NULL,0);


if (hInternet != NULL)
{
puts("internetOpen successfull");

HINTERNET hConnect =::InternetConnect(hInternet, url, INTERNET_DEFAULT_HTTP_PORT, NULL,NULL, INTERNET_SERVICE_HTTP,0,1u);

if (hConnect != NULL) {
puts("internetConnect successfull");

HINTERNET hRequest =::HttpOpenRequest(hConnect, TEXT("GET"), document, NULL, referer, 0, INTERNET_FLAG_KEEP_CONNECTION, 1);

if (hRequest != NULL) {
puts("HttpOpenRequest successfull");
//вот тут подвисает иногда!!! BOOL bSend = ::HttpSendRequest(hRequest, NULL,0, NULL,0);
if (bSend) {
puts("httpSendRequest successfull");

BOOL bRead = ::InternetReadFile(hRequest, szData,sizeof(szData)-1, &dwBytesRead);
if (bRead == FALSE || dwBytesRead == 0)
{
puts("error readFile");
return 0;
}

szData[dwBytesRead] = 0;
return szData;
}


::InternetCloseHandle(hRequest);
}


::InternetCloseHandle(hConnect);
}

/
::InternetCloseHandle(hInternet);
}


return 0;
}

Satell
24.08.2007, 15:52
как запихать ёё в отдельный поток?

NetMan
24.08.2007, 16:31
1) Делай структуру, содержащую из:
char* userag, char* proxy, char* url, char* document, char* referer
2) Заполни эту структуру
3) Создавай поток и передавай указатель на эту структуру (см. CreateThread)

Satell
24.08.2007, 19:57
у меня там ещё таймер есть, а getpage вызвается из обработчика события таймера в цикле, что тогда конкретно в потоке запускать? может есть где простой иходничек работы с потоками? а что происходит в том случае, если код в потоках ещё не отпработал, а наступает следующее событие таймера, например код в каком-то потоке не может получить страницу и подвис, этот код уничтожется или эти недоработавшие потоки будут висеть где-то в памяти?
а сам по себе таймер не создает отдельные потоки случайно?

int CALLBACK TimerProc(void)
{

for (int j=0; j<numsites; j++)
{

//поток должен создаваться гдето тут?!!!
pagedata=getpage(...);
//действия с pagedata

//ещё два раза
getpage(...);
getpage(...);
//поток должен заканчиваться гдето тут!!!

}

}

NetMan
25.08.2007, 14:46
у меня там ещё таймер есть, а getpage вызвается из обработчика события таймера в цикле, что тогда конкретно в потоке запускать?
Можешь, например, создавать отдельный поток для каждой страницы.
а что происходит в том случае, если код в потоках ещё не отпработал, а наступает следующее событие таймера, например код в каком-то потоке не может получить страницу и подвис, этот код уничтожется или эти недоработавшие потоки будут висеть где-то в памяти?
Таймер отдельно работает, потоки тоже отдельно. Следовательно недоработавшие потоки будут дорабатывать. ;)

Satell
30.08.2007, 23:24
делаю потоки таким образом с таймаутом 5 сек, виснуть перестало, но иногда возникает такое, что пропадает связь на модеме (нельзя открыть ничего в броузере) и все идет в таймаут "Can not connect to server" ровно раз в 5 сек, пока не завершишь программу, перегрузка какая-то чтоли, по идее все потоки должны завершаться через 5 сек, всё ли правильно в программе? а как сделать чтобы потоки работали параллельно несколько или они и так работают, но почему тогда puts(pThreadParm->url); выводит ровно раз в 5 сек...


DWORD WINAPI WorkerFunction( LPVOID );

typedef struct
{
char* url;
...структура данных для рабочей функции
} PARM;

int num=0;

DWORD WINAPI WorkerFunction(IN LPVOID vThreadParm)
//vThreadParm - points to PARM passed to thread
{
PARM* pThreadParm;
// Initialize local pointer to void pointer passed to thread
pThreadParm = (PARM*)vThreadParm;

...тут обрабатывающий код
puts(pThreadParm->url);

return 0;
}


int main(int argc, char* argv[])
{
DWORD dwTimeout;
PARM threadParm;

HANDLE hThread;
DWORD dwThreadID;


for (int j=0; j<num; j++)
{
hThread = CreateThread(
NULL, // Pointer to thread security attributes
0, // Initial thread stack size, in bytes
WorkerFunction, // Pointer to thread function
&threadParm, // The argument for the new thread
0, // Creation flags
&dwThreadID // Pointer to returned thread identifier
);

dwTimeout = 5000; // in milliseconds

if ( WaitForSingleObject ( hThread, dwTimeout ) == WAIT_TIMEOUT )
{
cout << "Can not connect to server";
}

CloseHandle (hThread);
}
}

Satell
31.08.2007, 11:17
в WorkerFunction вызывается getpage (см. первое сообщение), которая часто подвешивается, WaitForSingleObject ждёт 5 сек и потом по идее должна завершать поток, я думал это делает CloseHandle (hThread), но она этого не делает!!! копиться много потоков, пока не сожрут все ресурсы системы, как грамотно завершить поток?


if ( WaitForSingleObject ( hThread, dwTimeout ) == WAIT_TIMEOUT )
{
cout << "Can not connect to server";
ExitThread(dwThreadID); //при её использование тут программа просто виснет
TerminateThread(hThread,0); // говорят некорректно освобождает ресурсы, в общем все ресурсы системы все равно сжираются,
хотя потоков кажется меньше создаётся

}

Satell
31.08.2007, 15:18
HINTERNET hInternet;
HINTERNET hConnect;
HINTERNET hRequest;
объявляю глобально

потом

if ( WaitForSingleObject ( hThread, dwTimeout ) == WAIT_TIMEOUT )
{
cout << "Can not connect to server";
InternetCloseHandle(hInternet);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
WaitForSingleObject ( hThread, INFINITE );
}

так вот фиг, потоки все равно не завершаются при закрытии дескрипторов ф-й winapi(
виснет похоже HttpSendRequest и как повиснет так вместе с потоком и висит и ничего с ней не поделаешь, а если не ждать WaitForSingleObject ( hThread, INFINITE ); тогда число потоков постоянно растет... почему никто не придумал таймауты для ф-й winapi?

Ni0x
31.08.2007, 15:49
Люди, ну вы хотябы прежде чем писать многопоточные приложения, прочитайте про эту самую многопоточность.
Функция WaitForSingleObject() приостанавливает выполнение потока до тех пор, пока не произойдет одно из двух событий:

- истечет таймаут ожидания;

- ожидаемый объект перейдет в сигнальное (signaled) состояние.

По возвращаемому значению можно понять, какое из двух событий произошло. Ожидать с помощью wait-функций можно большинство объектов ядра, например, объект "процесс" или "поток", чтобы определить, когда они завершат свою работу.
http://uinc.ru/articles/38/
Надеюсь хоть что-то прояснишь для себя.

Satell
31.08.2007, 16:35
ну да я жду тут пока поток завершиться, а он не завершается, виснет ф-я HttpSendrequest и висит вместе с потоком, так их накапливается очень много, если не ждать

Satell
31.08.2007, 20:06
программа должна быстро коннектица к большому числу url
Как избавиться от зависания InternetOpenUrl или HttpSendRequest? зависает похоже на 5 мин, при недоступности сервера, таймаут этот гдето в настройках броузера, поменять его нельзя, закрытие описателей winapi ф-й в таймауте выполнения потока не помогает, если убивать потоки TerminateThread, то потом интернет ломается, нет связи, видимо не освобождаются какие-то ресурсы так, если забивать на зависшие потоки, то потом их становится очень много и опять же интернет ломается