Hi I have a QNetworkAccessManager which I use to send request to get image data from server. This call is asynchronous. I do multiple calls with it. Each call is done by opening a new instance of QNetworkAccessManager So when a specific condition occurs I want to stop the QNetworkAccessManager from receiving the replies from its network requests. Is there any way to do it? Thanks.
Don't use a new QNetworkAccessManager for each request but share the manager. It's usually fine to have just one. Of course one can have multiple if the application design suggests it - but e.g. managing multiple of them in a single controlling object is usually unnecessary. Just have one manager with the same lifetime as the object controlling the network requests.
To cancel running operations, keep the QNetworkReply* pointers QNetworkAccessManager::get/put/post return and call abort() when your condition occurs.
Connect to the finished() signal to remove them from the bookkeeping (as otherwise you would end up with dangling pointers).
If that becomes too complicated, think about using the command pattern. In this answer I describe why I find it particularly useful in this context.
Related
I am creating an application, that communicates with a server using an API's functions, from an existing code base written in C++/Qt 5.6 and Boost. The code is written in a way such that, any communication with the server is done by the API's functions that runs in a worker object. The worker object runs in a QThread(), and is moved using moveToThread.
My problem is that, I need to be able to stop the thread immediately and disconnect in the situation where the network connection drops. However, the thread blocks when it sends data to the server. If I try to stop the thread through quit() or wait(), the request still goes through to the server which is undesirable. The API doesn't offer any method to cancel any ongoing requests either.
My current solution is terminating the thread, and destroying the worker object it owns when the network connection drops. I then create a new QThread and new worker object when connecting to the server.
I know that terminate() or any kind of immediate termination of a thread should be avoided like the plague but it seems to work I think.
The worker object that runs in the QThread uses std::shared_ptr for it's members through std::make_shared.
Are there still chances of memory leaks/corruption?
Apart from this, because I create my QThread in a method, I receive a warning from QT:
QObject: cannot create children for a parent that is in a different thread
Despite this warning, my code still runs but I have doubts. Is it safe to ignore this warning? What are the risks/consequences of ignoring this?
Is it safer to litter the server connecting code with QT's interruption checking points/rewrite it in boost using boost::interruption_point instead of calling terminate? i.e
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
...
Advice much appreciated thanks.
I'm using Qt4.8 and I want to inject network faults into pre-existing code that uses QNetworkAccessManager. However, this class - and particularly the related QNetworkReply seem to have some strange semantics. I created a subclass of QNetworkAccessManager as well as one of QNetworkReply. My QTestNetworkAccessManager returns either an object created by the base QNetworkAccessManager, or the next test reply in the list:
QNetworkReply *QTestNetworkAccessManager
::createRequest( Operation op,
const QNetworkRequest &req,
QIODevice * outgoingData )
{
// QList<QTestNetworkReply*> m_replies;
if (m_replies.isEmpty())
{
return QNetworkAccessManager::
createRequest( op, req, outgoingData );
}
QTestNetworkReply* pReply = m_replies.takeFirst();
pReply->setUrl(req.url()); // lie about URLs
// this sets a timer that fires finished, etc.
pReply->queueFinished();
return pReply;
}
In the simple, trivial case of a single request, my test code seems to work, but two problems show up when I put it in a bigger app doing lots of network traffic.
First is QNetworkAccessManager seems to have private knowledge of the QNetworkReply objects it's creating. (based on inspecting the Qt source). For example it creates various flavors of QHttpReplyImpl and various other Impl objects and hooks them up in various ways, so my test objects don't seem to be good citizens in that environment. This seems to cause problems like error() signals not propagating correctly and my memory space is experiencing stack corruption.
(I'm not posting the entire QTextNetworkReply object because it's pretty simple and my question isn't really to troubleshoot my specific code.)
My question is: Has anyone done this kind of fault injection with QNetworkAccessManager and been able to simulate various HTTP faults.
One thought was to use the HttpProxy hooks to create a proxy server that actually injects data at the socket level so that it traverses the entire QHttp* object parser, but that seems like a lot of trouble.
Is there really no easier way to inject faults into QNetworkAccessManager so it acts like it is talking to a live server?
Thanks!
P.S. I am familiar with https://blogs.kde.org/2010/08/28/implementing-reusable-custom-qnetworkreply which is why I went down the road I'm on of subclassing QNAM, but it doesn't seem to handle the error semantics correctly and the gitorious link to the code is broken.
in my C++ based BlackBerry 10 app I have a custom class that uses QNetworkAccessManager to handle network connections. The requestFinished(..) method of QNetworkAccessManager object emits a signal when it receives some data.
The thing is, many outside classes are interested in this signal. So, I have many slots connected to this signal. My problem is that, in those slots, I may be doing some UI related stuff -- so I may not want that once the signal is emitted, ALL slots get called simultaneously all the time.
Rather I may want that, at one point in time, the signal calls only one slot, at another point in time, another slot, and etc. What are the ways to do this???
I thought I could do is using different QNetworkAccessManager objects (below) -- but I have heard it is not recommended??? e.g., what are other ways??? Thank you.
MyNetworkClass *network1 = new MyNetworkClass();
bool res = QObject::connect(network1, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot1(QVariant)));
MyNetworkClass *network2 = new MyNetworkClass();
bool res = QObject::connect(network2, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot2(QVariant)));
MyNetworkClass *network3 = new MyNetworkClass();
bool res = QObject::connect(network3, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot3(QVariant)));
By default, Qt application runs only 1 thread. This means nothing can be asyncronous. When one signal is fired, the slot function is run before anything else happens.
If you want to keep UI responsive and handle 3 functions at the same time, you need to thread them. At the beginning of the slot-function, start a thread where you execute the actual functionality.
http://doc.qt.digia.com/stable/thread-basics.html
Qt also has asynchronous functions:
http://doc.qt.digia.com/stable/qtconcurrentrun.html
Basically what Gjordis is saying you have to run the custom class where the QNetworkAccessManager resides asynchronously. You have 2 simple choices :
Either invoke asynchronous the methods of your class using QtConcurrent::run
Either handle this class events in another thread, see this excellent minimal example. The only thing is that the doWork() mentionned is really a doInit() or startWork() depending on the situation.
With both of these cases it is primordial to interact with the class only using signals and slots , otherwise you may encounter races conditions. Which means the "consumer" UI thread should not use getters\setters. Locking is not a good option, as the UI thread will require to perform an eventually blocking operation to get his data.
You should emit different signals in sequence from the same Object: a signal for every different object that is interested.
In this way you can decide the order and decide if send message to all or only to some.
I'm attempting to create a library whose API will be used in the following way:
WebService *service = new WebService( username, password );
User *user = service->getAuthenticatedUser();
UserAssets *assets = user->assets();
// And so on
Neither the authenticated user, nor their assets, will be downloaded when the WebServer instance is created, rather they will only be retrieved if explicitly requested.
Whenever I've had to retrieve data from the network before using Qt, I've followed the standard pattern of connection the finished() signal of the QNetworkReply to the appropriate slot and using that slot to handle the returned data.
My problem here is that pattern does not seem to accommodate my desired use-case. I would like the users of my library (other developers) to be able to use a single line to request and receive the data they desire, but the 'Qt way' seems, at least from my point of view, to require them to initiate the request on one line, and then connect some signal to some other slot to get the data back, which is not the experience I would like them to have.
I'm new to network programming, both in general and with Qt, but I've used libraries written in Python, communicating with the exact same service, that are able to achieve this, so it does seem to be possible.
Is it possible to perform the full lifecycle of a HTTP request with Qt with a single function call?
Your best bet is probably to use a QEventLoop. This would allow you to 1) initiate the HTTP connection and, from your caller's perspective, 2) effectively block until you get a response.
For example:
QNetworkReply wait for finished
As already other have mentioned you could use QEventLoop to wait for finished() or error() signals, and the quitting event loop. This solution while working, have some serious disadvantages.
If it takes longer to download given address, then you might be stuck in your event loop for quite a while. The event loop is processing events nicely, so your app doesn't frezze, but there are some quirks connected to it anyway. Imagine that user is waiting for load, and then presses another button, to load something else. Then you will have multiple loop-in-loop, and first file will have to wait for the second to finish downloading.
Doing things in single call suggest to many programmers, that this will happen at one instant. But your function is processing events internally, so this might not hold. Imagine a code like
// some pointer accessible to many functions/methods (eg. member, global)
MyData* myData=0;
Then a code calling your function:
if (myData){
QNetworkReply* reply = getMyWobsite(whatever);
myData->modify(reply);
}
Seems fine, but what if some other slot happens to call
myData=0;
If this slot will be executed while waiting for request, application will crash. If you decide to use QEventLoop in your function, be sure to mention it in function documentation, so programmers using it will be able to avoid such problems.
If you are not using qt for anything else, you might even consider some alternative libraries (eg. libcurl) that might have what you need already implemented.
I'm building a Qt application and using the QNetworkAccessManager to manager my http requests. Due to the asyncronous nature of QNetworkAccessManager you have to bind a slot to recieve the QNetworkReply when it's done.
I'm new to multithreaded design so I'm not sure how to handle this. I will have 3 seperate types of network replies which need to be parsed in the bound slot and then passed to the correct handler. One will extract a link, the 2nd will extract a picture, and the third will parse a post request's reply to verify that it was successful. All of this takes place within a QWidget subclass.
So, I'm wondering how this is normally handled. As I see it, based purely on intuition as I've done little reading on this specific subject, I would think there are two ways to handle this. One would be to rebind the network manager's finished() signal depending on the call and the other would be to use some sort of state flags and check those to see what the reply is expected to be. What is the preferred method, not necessarily between these two, that's just all I could think of myself, someone more experienced may well have a better solution.
Now, I'm also fairly new to c++, so if the later is the better way what's the best way to handle flags in this case? Would I use a bitset, an enum/flag setting function, or something else? Thanks guys!
If you know the type of reply you're going to get as a result of doing specific request you can connect void QNetworkReply::finished () signal to suitable handler.