Results 1 to 5 of 5

Thread: Thread Design Question

  1. #1
    Join Date
    Apr 2009
    Location
    Ottawa, Canada
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Thread Design Question

    Hi,
    I am just learning how to work with threads and I wanted to know if someone could help me with suggestions as to how I might go about solving the following problem. I don't need code (although it would be great), just some ideas on how to design my application.

    I have an application that needs to download a large number of large files from an FTP server and then perform some processing on those files. Since downloading will take quite a while I want to start processing files as their downloads complete. To further complicate things the 'processing' is being done by an external program that I will likely use by calling the C system() function.

    In reading the documentation for QSemaphore I thought I could modify the example program at:
    http://doc.trolltech.com/4.5/threads-semaphores.html
    for my needs.

    I would have a Producer class which downloads the file and a Conumser class which processes the file. My 'buffer' will simply be a list of file names (I use QFtp to get a listing beforehand) I want the Producer to acquire a filename and release it once completed. My Consumer would then acquire the filenames as they were released.

    My problems are:
    1. I use QFtp to download my files. If I start a download (or series of downloads) from Producer::run() how can I pause that thread until I get the Finished signal back from my QFtp notifying me that a download has been completed, so that I can then release a resource to the Consumer thread and start my next QFtp instance.

    2. In my Consumer thread I would like to know when the process spawned by my 'system()' calls finishes . My idea was to modify the program being called so that it outputs a temporary file when it finishes (I have access to the code), and occassionally check for this file as notification that the system call is done. Is there a better way to do this?

    Thank you for any suggestions.
    Craig

    2.

  2. #2
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread Design Question

    Have you considered using a QThreadPool instead of manually managing the threading? It could dramatically simplify your design while making it slightly more scalable.

    Also, if the external app used for processing accepts input from stdin you could use QProcess to stream the data from QFtp instead of waiting for the download to complete. Another advantage of using QProcess instead of system() is that it answers your second question.
    Current Qt projects : QCodeEdit, RotiDeCode

  3. The following user says thank you to fullmetalcoder for this useful post:

    craigdillabaugh (29th April 2009)

  4. #3
    Join Date
    Apr 2009
    Location
    Ottawa, Canada
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread Design Question

    Quote Originally Posted by fullmetalcoder View Post
    Have you considered using a QThreadPool instead of manually managing the threading? It could dramatically simplify your design while making it slightly more scalable.

    Also, if the external app used for processing accepts input from stdin you could use QProcess to stream the data from QFtp instead of waiting for the download to complete. Another advantage of using QProcess instead of system() is that it answers your second question.
    Thanks for the suggestions. I am looking into both. I am still confused. The following is a modified version of what is included in the QThreadPool docs that shows my specific problem:

    Qt Code:
    1. class DownLoader : public QRunnable
    2. {
    3. void run()
    4. {
    5. QFtp *ftp = new QFtp("ftp.site.url");
    6. QFile *file = new QFile();
    7. //Setup connection etc.
    8. //connect ftp's commandFinished to my commandFinished slot.
    9. ftp->get("filetodownload", cur_file);
    10. }
    11. public slots:
    12. void commandFinished(int commandId, bool error) { }
    13. }
    14.  
    15. DownLoader *d = new DownLoader();
    16. // QThreadPool takes ownership and deletes 'hello' automatically
    17. QThreadPool::globalInstance()->start(d);
    To copy to clipboard, switch view to plain text mode 

    Since ftp->get() returns immediately won't my Runnable terminate prior to the download completing and me receiving the commandFinished from my QFtp object. Also, I would close the file in commandFinished, so how can I make my run() wait and then close my file.

    This is of course the fundamental problem I have using regular threads too.

    Craig

  5. #4
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread Design Question

    The impossibility to block the ftp transfer is indeed an issue I overlooked which renders QThreadPool useless. However it implies that you don't need to create a thread per connection as QFtp does everything asynchronously anyway. Instead a single thread sending the get commands and waiting for them to finish (storing (command id, file name) pairs for further processing) would do.

    Also I am quite sure the above code will fail as the QFile to which you want to write the data pumped from QFtp does not point anywhere and is not opened in write mode.
    Current Qt projects : QCodeEdit, RotiDeCode

  6. The following user says thank you to fullmetalcoder for this useful post:

    craigdillabaugh (30th April 2009)

  7. #5
    Join Date
    Apr 2009
    Location
    Ottawa, Canada
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread Design Question

    Quote Originally Posted by fullmetalcoder View Post
    The impossibility to block the ftp transfer is indeed an issue I overlooked which renders QThreadPool useless. However it implies that you don't need to create a thread per connection as QFtp does everything asynchronously anyway. Instead a single thread sending the get commands and waiting for them to finish (storing (command id, file name) pairs for further processing) would do.

    Also I am quite sure the above code will fail as the QFile to which you want to write the data pumped from QFtp does not point anywhere and is not opened in write mode.
    Thanks again. I have a solution due to your suggestion. One thing I did find out is that it does not work to call QFtp::get() from within the run() method of a QThread as while the loop in the run() method is executing the signals from QFtp are apparently not received by my class derived from QThread (as far as I can see anyways).

    I've posted my (possibly not the best) solution below, in case anyone runs into the same problem. I simply run my downloader as a regular class and when a get() command finishes I launch the next ftp request. As files finish I can notify my data processing class by emitting a signal from my Downloader class (not shown).

    Qt Code:
    1. void FileDownloader::getNext() {
    2. //m_files is a QString vector holding all the filenames to download.
    3. //m_cur_file is a QFile* declared as a class variable.
    4. //m_counter is an int declared as a class variable.
    5.  
    6. if(m_counter == m_files.size()) {
    7. emit isDone();
    8. return;
    9. }
    10. else {
    11. m_cur_file = new QFile(m_files.at(m_counter++));
    12. if( !m_cur_file->open(QIODevice::WriteOnly)) {
    13. qDebug() << "Unable to open " << m_cur_file->fileName();
    14. }
    15. else {
    16. m_ftp->get(filename, m_cur_file);
    17. }
    18. }
    19. }
    20.  
    21. void FileDownloader::commandFinished(int commandId, bool error) {
    22. ....
    23. if (m_ftp->currentCommand() == QFtp::Get) {
    24. if (error ) {
    25. qDebug() << "Error downloading " << m_cur_file->fileName() << "\n";
    26. m_cur_file->close();
    27. m_cur_file->remove();
    28. }
    29. else {
    30. m_cur_file->close();
    31. }
    32. delete m_cur_file;
    33. m_cur_file = 0;
    34. getNext(); //Now fetch the next file - getNext() stops the process
    35. //once all files are received.
    36. }
    37. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. MDI design question
    By mooreaa in forum Qt Programming
    Replies: 8
    Last Post: 8th April 2011, 09:42
  2. QTableWidget Design & Thread Safety Question
    By bpetty in forum Qt Programming
    Replies: 4
    Last Post: 28th March 2008, 00:09
  3. KDE/QWT doubt on debian sarge
    By hildebrand in forum KDE Forum
    Replies: 13
    Last Post: 25th April 2007, 06:13
  4. A question of style and design
    By Kumosan in forum General Programming
    Replies: 7
    Last Post: 16th March 2007, 09:34
  5. simple thread layout question
    By mhoover in forum Qt Programming
    Replies: 1
    Last Post: 12th August 2006, 11:02

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.