×

Discussion Board

Results 1 to 13 of 13
  1. #1
    Regular Contributor
    Join Date
    Dec 2009
    Posts
    71

    QNetworkAccessManager and Qthread

    Hi all,

    I have some troubles to use QNetworkAccessManager in a thread. I know that QNetworkAccess works asynchronous but I need it in a thread.

    My thread is just a forever loop that wait for download some files. I use a QWaitCondition and QMutex to synchronize.

    When I launch my request, I never enter the finish handle. My handle is a slot. connected to the finish signal of the manager.
    I don't really understand why? I also put the accessmanager in the run() because as a class member, I can use it because the thread is not the parent.

    Can some one help me please.

    and also, what is the best wait to share QList and QHash between both thread? At the moment I create the QList and QHash in the main thread and give pointers to the thread. I use mutex to synchronize access. Is it the good way?

    Best regard.

  2. #2
    Super Contributor
    Join Date
    Oct 2009
    Posts
    4,326

    Re: QNetworkAccessManager and Qthread

    Apart from it doesn't look necessary to have a separate thread for QNetworkAccessManager, you need a running QEventLoop in your thread.

  3. #3
    Regular Contributor
    Join Date
    Dec 2009
    Posts
    71

    Re: QNetworkAccessManager and Qthread

    I try to use a QEventLoop like this :
    Code:
    QNetworkRequest request;
        request.setUrl(QUrl(_url));
        manager->get(request);
        qDebug()<<"[THREAD] launch request";
        waitDownloadEvent->exec();
    And I call waitDownloadEvent->exit(); in the handler but nothing happen because I don't receive the finished signal.

    I use a thread to download because I have some treatment to do after the download.
    Work with a thread can let my main app free. Do you think I'm doing bad?
    Last edited by Fillinger; 2010-09-01 at 12:08.

  4. #4
    Super Contributor
    Join Date
    Oct 2009
    Posts
    4,326

    Re: QNetworkAccessManager and Qthread

    It should be something like this:
    Code:
    void MyThread::run()
    {
        QNetworkRequest request;
        request.setUrl(QUrl(_url));
        manager->get(request);
        qDebug()<<"[THREAD] launch request";
        exec();
    }

  5. #5
    Regular Contributor
    Join Date
    Dec 2009
    Posts
    71

    Re: QNetworkAccessManager and Qthread

    always the same, the slot doesn't catch the signal.
    here is the run method:

    Code:
    void TileLoader::run()
    {
    
        QNetworkAccessManager *_manager = new QNetworkAccessManager();
    
        connect(_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(HandleNetworkData(QNetworkReply*)));
    
        forever
        {
           //Some treatment   
          
          //Wait condition
    
        //launch the download
         QNetworkRequest request;
        request.setUrl(QUrl(_url));
        manager->get(request);
        qDebug()<<"[THREAD] launch request";
        exec();
    
          
        }
    
    }
    something worng?

  6. #6
    Super Contributor
    Join Date
    Oct 2009
    Posts
    4,326

    Re: QNetworkAccessManager and Qthread

    Using forever is a bad idea. And how do you launch your thread?

  7. #7
    Regular Contributor
    Join Date
    Dec 2009
    Posts
    71

    Re: QNetworkAccessManager and Qthread

    Quote Originally Posted by divanov View Post
    Using forever is a bad idea. And how do you launch your thread?
    I launch my thread in a constructor of another class.


    QThread *th = new QThread();
    tl->moveToThread(th);
    tl->start();

    why is it a bad idea to use forever?
    Last edited by Fillinger; 2010-09-01 at 15:06.

  8. #8
    Regular Contributor
    Join Date
    Aug 2010
    Posts
    50

    Re: QNetworkAccessManager and Qthread

    have you finished your problem, I met it too.
    Can you show me tips if you resolved .
    Last edited by kongkong163; 2010-09-19 at 11:17.

  9. #9
    Super Contributor
    Join Date
    Oct 2009
    Posts
    4,326

    Re: QNetworkAccessManager and Qthread

    Quote Originally Posted by Fillinger View Post
    why is it a bad idea to use forever?
    Because your thread will never end execution.
    Last edited by divanov; 2010-09-21 at 08:03. Reason: fixing quote tag

  10. #10
    Super Contributor
    Join Date
    Jul 2008
    Posts
    2,020

    Re: QNetworkAccessManager and Qthread

    Moving a QNetworkAccessManager has various bad side effects I have documented in bug reports to JIRA: It is best to create the little f##er every time when you start the thread's run method.

    If you want me to, I can post you here my implementation!
    The lines above are the best I have to offer.If anyone of you is of more advanced knowledge, I ask for your patience and understanding! - unknown arab poet
    http://www.tamoggemon.com - Symbian blog - Windows Phone blog
    My other blogs:
    webOS blog iPhone blog BlackBerry blog Samsung bada blog Android blog

  11. #11
    Regular Contributor
    Join Date
    Aug 2010
    Posts
    50

    Re: QNetworkAccessManager and Qthread

    Can you show me your implementation and the bug reports link ? thanks

  12. #12
    Super Contributor
    Join Date
    Oct 2009
    Posts
    4,326

    Re: QNetworkAccessManager and Qthread

    This is the bug reported by Tam
    http://bugreports.qt.nokia.com/browse/QTBUG-13574
    Pay attention to Markus Goetz comment

  13. #13
    Super Contributor
    Join Date
    Jul 2008
    Posts
    2,020

    Re: QNetworkAccessManager and Qthread

    Hi Folks,
    update. I managed to get it to work, as it would have been to much effort to redo the entire app:
    Code:
    #include "QtFeedFetcher.h"
    #include "QtParseAtom.h"
    #include "QtParseRSS1.h"
    #include "QtParseRSS2.h"
    #include <QRegExp>
    #include <QXmlStreamReader>
    #include <QNetworkDiskCache>
    
    QtFeedFetcher::QtFeedFetcher(QString _feedURL)
    {//Runs in MAIN THREAD
    	myFeedURL=_feedURL;
    	myDoneFlag=false;
    	
    	myNWManager=NULL;
    }
    
    bool QtFeedFetcher::checkDone()
    {//Runs in MAIN THREAD
    	bool valCache;
    	myDoneFlagMutex.lock();
    	valCache=myDoneFlag;
    	myDoneFlagMutex.unlock();
    	return valCache;
    }
    
    QString QtFeedFetcher::checkErr()
    {//Runs in MAIN THREAD
    	return "";
    }
    
    void QtFeedFetcher::setUndone()
    {//Runs in MAIN THREAD
    	myDoneFlagMutex.lock();
    	myDoneFlag=false;
    	myDoneFlagMutex.unlock();
    }
    
    void QtFeedFetcher::run()
    {//Runs in AUXILLIARY THREAD
    
    	if(myNWManager!=NULL)
    	{
    		delete myNWManager;
    		myNWManager=NULL;
    	}
    	myNWManager=new QNetworkAccessManager();
    	myNWManager->moveToThread(this);
    	connect(myNWManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply *)));
    
    	
    	myDoneFlagMutex.lock();
    	myDoneFlag=false;
    	myDoneFlagMutex.unlock();
    	qDebug() << "Run" << currentThread();
    	
    	myOriginalUrl=myFeedURL;
    	if(myOriginalUrl.isValid())
    	{
    		QNetworkRequest request;
    		request.setUrl(myOriginalUrl);
    		request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
    		request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
    		//request.setRawHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
    		myNWManager->setCache(NULL);
    		myNWManager->get(request);
    		//Run the event loop
    		exec();
    	}
    	else
    	{
    		qDebug("Invalid URL!");
    	}
    	if(myNWManager!=NULL)
    	{
    		delete myNWManager;
    		myNWManager=NULL;
    	}
    }
    
    void QtFeedFetcher::replyFinished(QNetworkReply* reply) 
    {
    	/*
    	 * Reply is finished!
    	 * We'll ask for the reply about the Redirection attribute
    	 * http://doc.trolltech.com/qnetworkrequest.html#Attribute-enum
    	 */
    	qDebug() << "RepFi" << currentThread();
    	QVariant possibleRedirectUrl=reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
     
    	/* We'll deduct if the redirection is valid in the redirectUrl function */
    	myUrlRedirectedTo = this->redirectUrl(possibleRedirectUrl.toUrl(),myUrlRedirectedTo);
    	
    	/* If the URL is not empty, we're being redirected. */
    	if(!myUrlRedirectedTo.isEmpty()) 
    	{
    		//QString text = QString("QNAMRedirect::replyFinished: Redirected to ").append(myUrlRedirectedTo.toString());
    		
    		/* We'll do another request to the redirection url. */
    		QNetworkRequest request;
    		request.setUrl(myUrlRedirectedTo);
    		request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
    		request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
    		
    		myNWManager->get(request);
    	}
    	else 
    	{
    		/*
    		 * We weren't redirected anymore
    		 * so we arrived to the final destination...
    		 * 
    		 * Now we must device whom to feed
    		 */
    		QString readAll=reply->readAll();
    		QString headerCrappe=reply->header(QNetworkRequest::ContentTypeHeader).toString();
    		
    		QXmlStreamReader xml;
    		QtParseVirtual* virtualParser=NULL;
    		xml.clear();
    		xml.addData(readAll);
    		
    		if(readAll.contains(QRegExp("<rss +version\=\"2.0\"")))
    		{//Rss2, tested against http://cyber.law.harvard.edu/rss/examples/rss2sample.xml
    			//qDebug("RSS2");
    			virtualParser=new QtParseRSS2(&xml);
    		}
    		else if(readAll.contains(QRegExp("<rss +version\=\"0.92\"")))
    		{//Rss2==0.92, tested against http://cyber.law.harvard.edu/rss/examples/sampleRss092.xml
    			//qDebug("RSS0.92");	
    			virtualParser=new QtParseRSS2(&xml);
    		}
    		else if(readAll.contains(QRegExp("<rss +version\=\"0.91\"")))
    		{//Rss2==0.91, tested against http://cyber.law.harvard.edu/rss/examples/sampleRss091.xml
    			//qDebug("RSS0.91");			
    			virtualParser=new QtParseRSS2(&xml);
    		}
    		else if(headerCrappe.contains(QRegExp("application/atom")))
    		{//atom, tested against http://antone.geckotribe.com/alpha-gecko/categories/arts/poetry/feed/atom/
    			//qDebug("Atom");
    			virtualParser=new QtParseAtom(&xml);
    		}
    		else if(readAll.contains(QRegExp("<rdf")))
    		{//Untested Rss1 crap (not sure if we need it) - only if all others do not match
    			//qDebug("Rss1");
    			virtualParser=new QtParseRSS1(&xml);
    		}		
    		else
    		{
    			//qDebug("No Feed data found.");
    		}
    		
    		if(virtualParser!=NULL)
    		{
    			//qDebug("Directly parsing virtual");
    			myItems=virtualParser->processMe();
    			if(myItems.count()==0)goto other_else;
    		}
    		else
    		{//try to parse something
    			//TODO memory leak!!!!
    			other_else:
    			QVector<QtFeedItem*> myAtomItems;
    			QVector<QtFeedItem*> myRSS2Items;
    
    			virtualParser=new QtParseAtom(&xml);
    			myAtomItems=virtualParser->processMe();
    			
    			xml.clear();
    			xml.addData(readAll);
    			virtualParser=new QtParseRSS2(&xml);
    			myRSS2Items=virtualParser->processMe();
    			
    			if(myRSS2Items.count()>myAtomItems.count())
    			{
    				myItems=myRSS2Items;
    			}
    			else
    			{
    				myItems=myAtomItems;
    			}
    		}
    		myDoneFlagMutex.lock();
    		myDoneFlag=true;
    		myDoneFlagMutex.unlock();
    		delete virtualParser;
    		
    		/* ...so this can be cleared. */
    		myUrlRedirectedTo.clear();
    		//TODOdelete reply;
    		quit();
    	}
    	/* Clean up. */
    	//reply->deleteLater();
    	//TODOdelete reply;
    }
     
    QUrl QtFeedFetcher::redirectUrl(QUrl possibleRedirectUrl, QUrl oldRedirectUrl) 
    {
    	QUrl redirectUrl;
    	/*
    	 * Check if the URL is empty and
    	 * that we aren't being fooled into a infinite redirect loop.
    	 * We could also keep track of how many redirects we have been to
    	 * and set a limit to it, but we'll leave that to you.
    	 */
    	if(!possibleRedirectUrl.isEmpty() &&
    	   possibleRedirectUrl != oldRedirectUrl) {
    		redirectUrl = possibleRedirectUrl;
    	}
    	return redirectUrl;
    }
    The lines above are the best I have to offer.If anyone of you is of more advanced knowledge, I ask for your patience and understanding! - unknown arab poet
    http://www.tamoggemon.com - Symbian blog - Windows Phone blog
    My other blogs:
    webOS blog iPhone blog BlackBerry blog Samsung bada blog Android blog

Similar Threads

  1. Replies: 1
    Last Post: 2010-08-12, 10:27
  2. QThread and MainWindow (Qt designer)
    By darksoul_e in forum Qt
    Replies: 11
    Last Post: 2010-05-18, 14:12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •