подвисает wininet

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Satell, 24 Aug 2007.

  1. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    вот есть такой код получающий страницы по winnet,
    зачастую после вывода строки HttpOpenRequest Successfull перед функцией HttpSendRequest программа подвисает на несколько минут, либо очень надолго, можно ли сделать какой-нибудь таймаут для этих ф-й или как можно получать страницу с таймаутом?

    Code:
    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;
    }
    
    
     
    #1 Satell, 24 Aug 2007
    Last edited: 24 Aug 2007
  2. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    как запихать ёё в отдельный поток?
     
  3. NetMan

    NetMan Elder - Старейшина

    Joined:
    9 Feb 2004
    Messages:
    121
    Likes Received:
    37
    Reputations:
    34
    1) Делай структуру, содержащую из:
    char* userag, char* proxy, char* url, char* document, char* referer
    2) Заполни эту структуру
    3) Создавай поток и передавай указатель на эту структуру (см. CreateThread)
     
    1 person likes this.
  4. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    у меня там ещё таймер есть, а getpage вызвается из обработчика события таймера в цикле, что тогда конкретно в потоке запускать? может есть где простой иходничек работы с потоками? а что происходит в том случае, если код в потоках ещё не отпработал, а наступает следующее событие таймера, например код в каком-то потоке не может получить страницу и подвис, этот код уничтожется или эти недоработавшие потоки будут висеть где-то в памяти?
    а сам по себе таймер не создает отдельные потоки случайно?

    int CALLBACK TimerProc(void)
    {

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

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

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

    }

    }
     
  5. NetMan

    NetMan Elder - Старейшина

    Joined:
    9 Feb 2004
    Messages:
    121
    Likes Received:
    37
    Reputations:
    34
    Можешь, например, создавать отдельный поток для каждой страницы.
    Таймер отдельно работает, потоки тоже отдельно. Следовательно недоработавшие потоки будут дорабатывать. ;)
     
  6. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    делаю потоки таким образом с таймаутом 5 сек, виснуть перестало, но иногда возникает такое, что пропадает связь на модеме (нельзя открыть ничего в броузере) и все идет в таймаут "Can not connect to server" ровно раз в 5 сек, пока не завершишь программу, перегрузка какая-то чтоли, по идее все потоки должны завершаться через 5 сек, всё ли правильно в программе? а как сделать чтобы потоки работали параллельно несколько или они и так работают, но почему тогда puts(pThreadParm->url); выводит ровно раз в 5 сек...

    Code:
    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);
    }
    }
    
    
     
  7. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    в WorkerFunction вызывается getpage (см. первое сообщение), которая часто подвешивается, WaitForSingleObject ждёт 5 сек и потом по идее должна завершать поток, я думал это делает CloseHandle (hThread), но она этого не делает!!! копиться много потоков, пока не сожрут все ресурсы системы, как грамотно завершить поток?

    Code:
    if ( WaitForSingleObject ( hThread, dwTimeout ) == WAIT_TIMEOUT )
    {
               cout << "Can not connect to server";
               ExitThread(dwThreadID);       //при её использование тут программа просто виснет
               TerminateThread(hThread,0); // говорят некорректно освобождает ресурсы, в общем все ресурсы системы все равно сжираются, 
    хотя потоков кажется меньше создаётся
                                                  
    }
    
     
    #7 Satell, 31 Aug 2007
    Last edited: 31 Aug 2007
  8. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    HINTERNET hInternet;
    HINTERNET hConnect;
    HINTERNET hRequest;
    объявляю глобально

    потом
    Code:
    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?
     
    #8 Satell, 31 Aug 2007
    Last edited: 31 Aug 2007
  9. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Люди, ну вы хотябы прежде чем писать многопоточные приложения, прочитайте про эту самую многопоточность.
    http://uinc.ru/articles/38/
    Надеюсь хоть что-то прояснишь для себя.
     
    1 person likes this.
  10. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    ну да я жду тут пока поток завершиться, а он не завершается, виснет ф-я HttpSendrequest и висит вместе с потоком, так их накапливается очень много, если не ждать
     
  11. Satell

    Satell Elder - Старейшина

    Joined:
    13 Jan 2007
    Messages:
    91
    Likes Received:
    5
    Reputations:
    1
    программа должна быстро коннектица к большому числу url
    Как избавиться от зависания InternetOpenUrl или HttpSendRequest? зависает похоже на 5 мин, при недоступности сервера, таймаут этот гдето в настройках броузера, поменять его нельзя, закрытие описателей winapi ф-й в таймауте выполнения потока не помогает, если убивать потоки TerminateThread, то потом интернет ломается, нет связи, видимо не освобождаются какие-то ресурсы так, если забивать на зависшие потоки, то потом их становится очень много и опять же интернет ломается