Results 1 to 9 of 9

Thread: Seeking design advise

  1. #1
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Seeking design advise

    I have following scenario:

    My code invokes external function (some type of print) in the loop.
    In each iteration, after variable amount of time (< 2 mins) it saves
    the file in the specific directory or it may fail to print and I need to advance to the next loop cycle.

    Logically it is like that:
    Qt Code:
    1. while (1)
    2. {
    3. // waitfor returns true if file is found. If 3 minutes passed and file
    4. // is not found where it is supposed to be, do nothing
    5. if (waitfor (printfile(), 3))
    6. {
    7. // do something with the file
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 

    Printfile should monitor the appearance of the file in a certain directory. If not found in 2 mins, proceed to the next loop.
    I am perfectly capable of doing something with straight c++ or boost. I am interested in understanding
    how it can be implemented using specialized Qt classes, like QFileSystemWatcher, QFuture or others.
    In QFileSystemWatcher, for example, I don't see how can I do wait without putting some wait conditions in the slot;

    Advise is greatly appreciated.

    Thanks.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,513
    Thanks
    13
    Thanked 1,574 Times in 1,503 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Seeking design advise

    Are you expecting your waiting program to be doing something while it waits?

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    3,929
    Thanks
    229
    Thanked 615 Times in 605 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Seeking design advise

    My code invokes external function (some type of print) in the loop.
    Is this something you spawn using QProcess? Then you can implement a slot that handles one of the QProcess signals.

    Are you expecting your waiting program to be doing something while it waits?
    If not, then using something like QFileSystemWatcher might be a good solution, but it won't handle the case where creating the file fails (ie. the print doesn't work). But any code that uses a while( true ) infinite loop is potential for big trouble. If you have to do that, then you should at least insert a processEvents() call in the loop to keep the app from freezing.

    The QFuture methods that query for a result are blocking, so they will cause your app to hang until that process is complete. That's about as bad as an infinite loop.

    I am curious, though. Most operating systems I am familiar with implement some kind of print queue. So you should be able to send multiple print requests, and the printing system will queue them up and process them in order. Why do you have to wait until one finishes before starting the next one? The OS print queue will do that for you. So if you can do away with waiting, then QFileSystemWatcher will probably serve to tell you when a print job has created a file successfully.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  4. #4
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    Quote Originally Posted by ChrisW67 View Post
    Are you expecting your waiting program to be doing something while it waits?
    No, just sit and wait until either new file is generated or timeout occures.


    Added after 6 minutes:


    The process I am describing is a specialized screen scraping process, so it is sequential in nature and I do have to wait until individual screen view is processed.
    Last edited by TorAn; 2nd March 2019 at 09:45.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,190
    Thanks
    36
    Thanked 1,489 Times in 1,441 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    Quote Originally Posted by TorAn View Post
    In QFileSystemWatcher, for example, I don't see how can I do wait without putting some wait conditions in the slot;
    With this approach the waiting is done implicitly, i.e. the object registers itself with the platform's file notification system and relays notifications for files that it is told to watch.

    The "loop" in this case is the thread's event loop so it is not really useful of you are running your own loop.

    So its main use case is to trigger functionality when a file appears, is changed or disappears.
    I.e. as the source that triggers an action, not as part of a larger processing chain.

    Cheers,
    _

  6. #6
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    I wrote the test that I think covers suggestions that were given (and much appreciated):

    Qt Code:
    1. class scraper: public QRunnable
    2. {
    3. private:
    4. int _id;
    5. QMutex& _mtx;
    6. QString _path;
    7. public:
    8. scraper(int id, QMutex& m, QString p) : _id(id), _mtx(m), _path(p) {}
    9. void run() {
    10. qfs.addPath(_path);
    11.  
    12. // this slot is never called, despite moving file to the path. I think it is because it executes in the main thread;
    13. if (! QObject::connect(&qfs, &QFileSystemWatcher::directoryChanged, [&](const QString& p){
    14. qDebug() << "cycle:" << QString::number(_id) << "file:" <<p;
    15. _mtx.unlock();
    16. })) {
    17. qDebug() << "failure to connect to QFileSystemWatcher::directoryChanged signal";
    18. return;
    19. }
    20. qDebug() << "waiting for file in cycle " << QString::number(_id);
    21. }
    22. };
    23.  
    24. int main(int argc, char *argv[])
    25. {
    26. QCoreApplication a(argc, argv);
    27. qDebug()<< "started";
    28. QMutex mtx;
    29. QString pt="c:/temp/files";
    30. QTimer::singleShot(2000,&a, [&](){
    31. for (int i = 0; i < 20; ++i) {
    32. qDebug() << "starting cycle " << QString::number(i);
    33. scraper* myscraper = new scraper(i, mtx, pt);
    34. QThreadPool::globalInstance()->start(myscraper);
    35. mtx.lock();
    36. wc.wait(&mtx, 20000);
    37. mtx.unlock();
    38. }
    39. });
    40. return a.exec();
    41. }
    To copy to clipboard, switch view to plain text mode 
    The issue I am having is that the signal directoryChanged is never called. I think it is because it is a queued call and it is executed in the context of the main thread which is blocked. Perhaps I should use QThread instead of QRunnable? Suggestions and critiques are always welcomed and appreciated. Thanks!

  7. #7
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,430
    Thanked 264 Times in 259 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    I think that directoryChanged signal is emited but qfs is deleted on exit from run(). Declare qfs like _mtx and _path.

  8. #8
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    Thanks, I will try that.

    Update - I don't think that the destruction of the instance is the problem. I changed the code to this:

    Qt Code:
    1. class scraper: public QRunnable
    2. {
    3. private:
    4. int _id;
    5. QMutex& _mtx;
    6. QString _path;
    7. public:
    8. scraper(int id, QMutex& m, QString p) : _id(id), _mtx(m), _path(p) {
    9. setAutoDelete(false);
    10. }
    To copy to clipboard, switch view to plain text mode 

    So, autodestruction does not happen and QFileSystemWatcher is "alive". Slot is not called though when I copy the file to the directory.
    Last edited by TorAn; 6th March 2019 at 15:05.

  9. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,190
    Thanks
    36
    Thanked 1,489 Times in 1,441 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Seeking design advise

    Quote Originally Posted by TorAn View Post
    The issue I am having is that the signal directoryChanged is never called.
    Your thread doesn't run an event loop, so the file system watcher never start its work.
    I.e. your run() method immediately exists after setting up the object and its connection.

    Qt Code:
    1. void run() {
    2. QEventLoop loop;
    3. qfs.addPath(_path);
    4.  
    5. // this slot is never called, despite moving file to the path. I think it is because it executes in the main thread;
    6. if (! QObject::connect(&qfs, &QFileSystemWatcher::directoryChanged, [&](const QString& p){
    7. qDebug() << "cycle:" << QString::number(_id) << "file:" <<p;
    8. loop.quit();
    9. _mtx.unlock();
    10. })) {
    11. qDebug() << "failure to connect to QFileSystemWatcher::directoryChanged signal";
    12. return;
    13. }
    14. qDebug() << "waiting for file in cycle " << QString::number(_id);
    15. loop.exec();
    16. }
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by TorAn View Post
    I think it is because it is a queued call and it is executed in the context of the main thread which is blocked.
    No, the QFileSystemWatcher is created in run(), which is executed by a separate thread.
    So all its event handling happens in that thread.
    But handling events requires a running event loop.

    Quote Originally Posted by TorAn View Post
    Perhaps I should use QThread instead of QRunnable?
    I don't really understand why you need a thread at all.

    Cheers,
    _

Similar Threads

  1. Seeking advise on the QtScript replacement
    By TorAn in forum Qt Programming
    Replies: 3
    Last Post: 5th November 2015, 17:18
  2. Seeking Suggestions for Multi-Threaded Application Design
    By swamyonline in forum Qt Programming
    Replies: 7
    Last Post: 1st May 2014, 17:19
  3. UI like Guitar Pro 6 - Please advise me.
    By jeanremi in forum Qt Programming
    Replies: 4
    Last Post: 20th May 2011, 09:26
  4. advise sought on TreeView model design
    By QPlace in forum Qt Programming
    Replies: 0
    Last Post: 25th June 2009, 15:36
  5. Replies: 3
    Last Post: 6th October 2008, 00:41

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.