Discussion:
[Interest] QNetworkAccessManager in a command line, non-eventloop application
Scott Aron Bloom
2013-01-18 00:59:13 UTC
Permalink
I have a command line application, with no event loop.

I also have a function where I need the tool to send a HTML request out, and not care about the result..

There is 1 and only 1 QNAM.

I know what the issue is, there is NO event loop, what I would like to do is have a QThread (or a concurrent class equivalent) for the requests. I just push a request into the thread, which has its own event loop.

Then I want to simply wait at the end of the command line tool, for the Thread to finish..

I have tried all sorts of crap (and yes I admit its crap) code for the QThread based approach.. Any help would be appreciated.

Scott

std::list< QNetworkReply * > replies;
void sendRequest()
{
QNetworkReply * reply = nam.get( QNetworkRequest( QUrl( "http://www.google.com" ) ) );
replies.push_back( reply );
}

bool isRequstPending()
{
Bool hasPending = false;
For( std::list<QNetworkReply * >::iterator ii = replies.begin(); !hasPending && ii != replies.end(); ++ii )
{
hasPending = (*ii)->isFinished();
}
return hasPending;
}

int main( int argc, char ** argv )
{
QCoreApplication appl( argc, argv );
sendRequest();
sendRequest();
sendRequest();
sendRequest();

while( isRequestPending() )
{
}
}
Thiago Macieira
2013-01-18 01:27:16 UTC
Permalink
Post by Scott Aron Bloom
I have a command line application, with no event loop.
We can stop here. QNetworkAccessManager requires an event loop.

But if you're going to block anyway in order to do work, you can use
QEventLoop to start the event loop until the request finishes.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Scott Aron Bloom
2013-01-18 01:49:35 UTC
Permalink
-----Original Message-----
From: interest-bounces+scott.bloom=***@qt-project.org [mailto:interest-bounces+scott.bloom=***@qt-project.org] On Behalf Of Thiago Macieira
Sent: Thursday, January 17, 2013 5:27 PM
To: ***@qt-project.org
Subject: Re: [Interest] QNetworkAccessManager in a command line, non-eventloop application
Post by Scott Aron Bloom
I have a command line application, with no event loop.
We can stop here. QNetworkAccessManager requires an event loop.

But if you're going to block anyway in order to do work, you can use QEventLoop to start the event loop until the request finishes.
----------

I don't want to block :)

I would like a background thread and have the request run in there, using the QThreads event loop.

Scott
Mandeep Sandhu
2013-01-18 09:02:24 UTC
Permalink
On Fri, Jan 18, 2013 at 7:19 AM, Scott Aron Bloom
Post by Scott Aron Bloom
-----Original Message-----
Sent: Thursday, January 17, 2013 5:27 PM
Subject: Re: [Interest] QNetworkAccessManager in a command line, non-eventloop application
Post by Scott Aron Bloom
I have a command line application, with no event loop.
We can stop here. QNetworkAccessManager requires an event loop.
But if you're going to block anyway in order to do work, you can use QEventLoop to start the event loop until the request finishes.
----------
I don't want to block :)
I would like a background thread and have the request run in there, using the QThreads event loop.
But you still are waiting for this thread to finish work and then quit
the app, correct?

Just curious here, but why don't you want to run the event loop in the
main thread but only run it in a different thread?

-mandeep
Post by Scott Aron Bloom
Scott
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
R. Reucher
2013-01-18 09:28:34 UTC
Permalink
Post by Mandeep Sandhu
Just curious here, but why don't you want to run the event loop in the
main thread but only run it in a different thread?
Probably because the environment it's going to be used in already utilizes its
own event loop... I had a similar situation once when I wrote a Samba VFS
plugin with Qt, mainly for being able to use QThread's.

However, doesn't the QNAM also work in a QThread which runs its own event
loop?!

HTH, René
Scott Aron Bloom
2013-01-18 17:05:53 UTC
Permalink
Post by Scott Aron Bloom
-----Original Message-----
Behalf Of Thiago Macieira
Sent: Thursday, January 17, 2013 5:27 PM
Subject: Re: [Interest] QNetworkAccessManager in a command line, non-eventloop application
Post by Scott Aron Bloom
I have a command line application, with no event loop.
We can stop here. QNetworkAccessManager requires an event loop.
But if you're going to block anyway in order to do work, you can use QEventLoop to start the event loop until the request finishes.
----------
I don't want to block :)
I would like a background thread and have the request run in there, using the QThreads event loop.
But you still are waiting for this thread to finish work and then quit the app, correct?

Just curious here, but why don't you want to run the event loop in the main thread but only run it in a different thread?

-mandeep
--------------
99% (ok made up number) of the runs, take minutes (some 10s of hours, some 1-2 seconds), the 1-2 seconds in the thread will be done way way before the application is finished.

In the SMALL number of cases, its ok to block the exit of the application.

The HTTP request is made at the startup of the application

Scott
Thiago Macieira
2013-01-18 09:50:34 UTC
Permalink
Post by Scott Aron Bloom
I don't want to block
I would like a background thread and have the request run in there, using
the QThreads event loop.
The background thread runs an event loop, sure, but what is the main thread
doing in the meantime? Since it doesn't have an event loop, it cannot receive
events. The only synchronisation mechanisms left are QWaitCondition and
QSemaphore, which means the main thread must block waiting for the background
thread to finish the operation.

You really don't have a choice besides those two. Network access is not
instantaneous. You must either use the event loop or you need to block.

Choose one.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Scott Aron Bloom
2013-01-18 17:08:46 UTC
Permalink
Post by Scott Aron Bloom
I don't want to block
I would like a background thread and have the request run in there,
using the QThreads event loop.
The background thread runs an event loop, sure, but what is the main thread doing in the meantime? Since it doesn't have an event loop, it cannot receive events. The only synchronisation mechanisms left are QWaitCondition and QSemaphore, which means the main thread must block waiting for the background thread to finish the operation.

You really don't have a choice besides those two. Network access is not instantaneous. You must either use the event loop or you need to block.

Choose one.
-----------------------------
Blocking at the end, is ok... Blocking while the application is running is not. Yes, I want my cake and to eat is as well :)

I essentially want to kick off the request at the beginning of the run, then let the request run its course in the backround.

If the main application (no event loop at all, non-event driven, nonQt for the most part), finishes first (rare occasion) I can block on the background thread ending. However most times, the single http request will have finished long before

Scott
Thiago Macieira
2013-01-18 21:38:23 UTC
Permalink
Post by Thiago Macieira
Post by Scott Aron Bloom
I don't want to block
I would like a background thread and have the request run in there,
using the QThreads event loop.
The background thread runs an event loop, sure, but what is the main thread
doing in the meantime? Since it doesn't have an event loop, it cannot
receive events. The only synchronisation mechanisms left are QWaitCondition
and QSemaphore, which means the main thread must block waiting for the
background thread to finish the operation.
You really don't have a choice besides those two. Network access is not
instantaneous. You must either use the event loop or you need to block.
Choose one.
-----------------------------
Blocking at the end, is ok... Blocking while the application is running is
not. Yes, I want my cake and to eat is as well :)
If you don't block, then you have a loop. Maybe you don't have Qt's event loop
mechanism (QEventLoop), but you have an event loop nonetheless.

Since you can't use Qt events for this and you don't want to make a blocking
call, you may use a QSemaphore tryAcquire() or equivalent to check whether the
work is done. But you also need to determine when your main thread's other
business is done, because then you'll need to use acquire() instead and block
(if you don't, you'll have a busy-wait loop).

In other words, your solution is to have *both* blocking calls and a loop.
Post by Thiago Macieira
I essentially want to kick off the request at the beginning of the run, then
let the request run its course in the backround.
If the main application (no event loop at all, non-event driven, nonQt for
the most part), finishes first (rare occasion) I can block on the
background thread ending. However most times, the single http request will
have finished long before
You describe a "fire-and-forget" situation: you kick off the request and you
don't care when it finishes. You'd only have to care that the application
doesn't exit before the request is finished processing.

However, there's no such thing as a "fire-and-forget" network request. Even the
simplest request (a PUT) results in a success or failure result. I imagine
your application is interested in whether the request failed, as it may need
to take some action in that case.

That means you need to rearchitect your application so that it can receive the
communication from the other thread. So we go back to an event loop or a
blocking call. Or both.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Scott Aron Bloom
2013-01-20 17:29:59 UTC
Permalink
Post by Thiago Macieira
Post by Scott Aron Bloom
I don't want to block
I would like a background thread and have the request run in there,
using the QThreads event loop.
The background thread runs an event loop, sure, but what is the main
thread doing in the meantime? Since it doesn't have an event loop, it
cannot receive events. The only synchronisation mechanisms left are
QWaitCondition and QSemaphore, which means the main thread must block
waiting for the background thread to finish the operation.
You really don't have a choice besides those two. Network access is
not instantaneous. You must either use the event loop or you need to block.
Choose one.
-----------------------------
Blocking at the end, is ok... Blocking while the application is
running is not. Yes, I want my cake and to eat is as well :)
If you don't block, then you have a loop. Maybe you don't have Qt's event loop mechanism (QEventLoop), but you have an event loop nonetheless.

Since you can't use Qt events for this and you don't want to make a blocking call, you may use a QSemaphore tryAcquire() or equivalent to check whether the work is done. But you also need to determine when your main thread's other business is done, because then you'll need to use acquire() instead and block (if you don't, you'll have a busy-wait loop).

In other words, your solution is to have *both* blocking calls and a loop.
Post by Thiago Macieira
I essentially want to kick off the request at the beginning of the
run, then let the request run its course in the backround.
If the main application (no event loop at all, non-event driven, nonQt
for the most part), finishes first (rare occasion) I can block on the
background thread ending. However most times, the single http request
will have finished long before
You describe a "fire-and-forget" situation: you kick off the request and you don't care when it finishes. You'd only have to care that the application doesn't exit before the request is finished processing.

However, there's no such thing as a "fire-and-forget" network request. Even the simplest request (a PUT) results in a success or failure result. I imagine your application is interested in whether the request failed, as it may need to take some action in that case.

That means you need to rearchitect your application so that it can receive the communication from the other thread. So we go back to an event loop or a blocking call. Or both.

--

Actually I don't care about result, even if it fails.. I understand it will return a result, but I really don't need it or want it...

Honestly, if qNAM had the ability to set the timeout, I would have no problem with a blocking call.. But when the machine is off network, and can take up to 30 seconds to timeout... I cant have the application block for that long...

Scott
Giuseppe D'Angelo
2013-01-20 18:21:20 UTC
Permalink
Post by Scott Aron Bloom
Honestly, if qNAM had the ability to set the timeout, I would have no problem with a blocking call..
Start a QTimer and abort the QNetworkReply if it fires before
finished(), and viceversa.

Cheers,
--
Giuseppe D'Angelo
Mandeep Sandhu
2013-01-19 16:06:27 UTC
Permalink
Post by Scott Aron Bloom
Blocking at the end, is ok... Blocking while the application is running is not. Yes, I want my cake and to eat is as well :)
I essentially want to kick off the request at the beginning of the run, then let the request run its course in the backround.
If the main application (no event loop at all, non-event driven, nonQt for the most part), finishes first (rare occasion) I can block on the background thread ending. However most times, the single http request will have finished long before
You can enqueue your requests to this thread, do all n/w processing
there and exit the thread when its done with all the requests.

Meanwhile in the main thread you can wait for this helper thread to
finish (QThread::wait()). If its not running, thne u exit away
immediately, else wait till that thread exits and then quit your main
app. Will that work?

HTH,
-mandeep
Post by Scott Aron Bloom
Scott
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Loading...