Results 1 to 6 of 6

Thread: Thread related problems with QNetworkAccessmanager

  1. #1
    Join Date
    Oct 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Thread related problems with QNetworkAccessmanager

    I have a QNetWorkAccessManager object created in thread 1 (main GUI thread).

    Later, a different thread wishes to use it, like this:

    Qt Code:
    1. QNetworkReply *reply = _manager->get(request_);
    To copy to clipboard, switch view to plain text mode 

    This results in the error message to console:
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QNetworkAccessManager(0x146a3c0), parent's thread is QThread(0x134f500), current thread is QThread(0x3261ca0)
    I read about it, and find that I should not have the function get execute in the thread that the QNetworkAccessManager was not created in.

    I then find that I can use moveToThread() to fix this. I add code:

    Qt Code:
    1. _manager->moveToThread(QThread::currentThread());
    2. QNetworkReply *reply = _manager->get(request_);
    To copy to clipboard, switch view to plain text mode 

    This does not work, with the following error to console:
    QObject::moveToThread: Current thread (0x2b44b20) is not the object's thread (0x134f500).
    Cannot move to target thread (0x2b44b20)
    I read up on moveToThread(), and I think the problem here is that I can only do this in the thread that the QNetworkAccessManager is in. That is, I have to run the function moveToThread() in the thread that the QNetworkAccessManager is currently "in", or "has affinity with", which is probably thread one (main GUI thread). I can push the QNetworkAccessManager from that original thread to the current thread, but I cannot pull it from the current thread.

    At this point, this is starting to look like a lot of work and I think I must be missing something. There must be a better, "right" way to do this. To create a QNetworkAccessManager object in the main GUI thread and then use it from other threads. What am I missing? How is this meant to be done?

  2. #2
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Thread related problems with QNetworkAccessmanager

    Indeed, there is a better way: do not use threads for your networking code.

    QNetworkAccessManager is not meant to be used in different threads. Each QNetworkReply spawned by the manager emits signals when data is ready or when the request has finished. You can keep all your networking code in the main thread just by connecting to those signals. Of course, this means that your code is scattered around the program: a block of code sends the request, another block deals with the reply. But hey, this is just event-driven programming.

    Why do you need threads in the first place? If you need them because of some heavy computation on the data received in the reply, you can read the reply in the main thread and pass the data to a thread, or a function run with QtConcurrent:run().

  3. #3
    Join Date
    Oct 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread related problems with QNetworkAccessmanager

    The bigger picture is that this is part of a much larger process that takes a long long time, and this network use happens in the middle of it. To avoid freezing the GUI, this larger process happens in a different thread and provides updates to the GUI so the GUI can have a nice progress bar and tell the user interesting things about what is happening.

    So it sounds like I need to have this process still happen in a different thread, but instead of having it do its own
    Qt Code:
    1. QNetworkReply *reply = _manager->get(request_);
    To copy to clipboard, switch view to plain text mode 
    I need this secondary, non-GUI process to emit a signal that then causes
    Qt Code:
    1. QNetworkReply *reply = _manager->get(request_);
    To copy to clipboard, switch view to plain text mode 
    to happen in the main thread, and have the secondary process then wait around until the reply object emits a signal saying it's finished?
    Last edited by Moschops; 20th October 2015 at 14:19.

  4. #4
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Thread related problems with QNetworkAccessmanager

    Yes, you can almost do that. For instance:

    In the secondary thread, emit a signal, e.g. dataRequested(QUrl), when you need the data, then wait with a QEventLoop for the reply to be ready/an error to occur.

    In the main thread, connect dataRequested(QUrl) to a slot that sends the request through the QNetworkAccessManager, then deal with the reply. When the reply has finished, read the data or determine the error, store this information somewhere, then unblock the secondary thread by sending a signal previously connected the the QEventLoop's quit() slot.

    The secondary thread can then read the reply and check for any error, then continue its execution.

    There are alternatives, e.g. using mutexes and wait conditions.

    This QEventLoop-based solution is adapted to situations with a complex context, e.g. if the network request happens in the middle of a nested loop or in a recursive call. In simpler cases you can just redesign the code in the secondary thread to be event-driven, and let QThread::run() run an event loop (which is what the default implementation does).

  5. The following user says thank you to yeye_olive for this useful post:

    Moschops (20th October 2015)

  6. #5
    Join Date
    Oct 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread related problems with QNetworkAccessmanager

    I think some kind of redesign may be in order. Perhaps I can find a way to get the QNetworkAccessManager call done in advance in the main thread, and just carry the information forwards into the heavy processing. That would not only solve the problem, but do it by making things simpler. Thanks very much for your words.

  7. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Thread related problems with QNetworkAccessmanager

    Or you just use a network access manager that got created in the thread.
    Requires a thread with running event loop though.

    Cheers,
    _

Similar Threads

  1. Thread related questions
    By Cruz in forum Qt Programming
    Replies: 11
    Last Post: 22nd February 2011, 11:57
  2. QNetworkAccessManager + DiskCache => use Thread?
    By Coolcat in forum Qt Programming
    Replies: 4
    Last Post: 20th January 2011, 22:52
  3. Multi-thread related problem,help me
    By mendynew in forum Qt Programming
    Replies: 2
    Last Post: 3rd November 2008, 04:02
  4. Problem related exiting the thread
    By raghvendramisra in forum Qt Programming
    Replies: 1
    Last Post: 16th July 2008, 11:10

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.