Results 1 to 8 of 8

Thread: Separating load of GUI and worker thread

  1. #1
    Join Date
    Dec 2010
    Posts
    14
    Thanks
    1

    Default Separating load of GUI and worker thread

    Hi everyone,

    I need some advice . I have a gui application written in Qt. The application calls some computationally intensive threads , they are computer vision or computational geometry implementations.

    I have used QThread API for creating the threads.

    The problem I am facing is even though algorithms are being executed in separate worker threads , they still affect the GUI and make it pretty unresponsive , in fact they even affect
    all other applications running in the OS. I am using windows 7 64 bit on dual core processor. In windows resource manager I see the CPU usage , the worker thread never takes more than
    50% of CPU and there is plenty of main memory free , so the resources are available in plenty , but still if click on GUI while the worker thread is running , the GUI becomes pretty
    unresponsive for 15 to 20 seconds , then it responds in pretty flickery way.

    One more important thing to notice is that , the application runs perfectly in unix environment.

    Here is one of the slot

    ..................

    textureGenerator is the thread here , I start it from one of the slots of the main GUI app.

    generateTextureAct->setDisabled( true );

    textureGenerator->load_calibration( hybridNccReconstructor->get_calibration() );

    std::cout<<" project name : "<<projectName<<std::endl;

    textureGenerator->set_project_name( projectName );

    vtkPolyData *_meshed_data = vtkPolyData::New();

    model.get_output( _meshed_data );

    textureGenerator->set_working_directory( working_directory );

    textureGenerator->load_data( _meshed_data );

    textureGenerator->start();

    ...............

    Any help would be greatly appreciated.

    Thanks a lot.

    Avanindra Singh

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Separating load of GUI and worker thread

    What does the implementation of the thread itself look like?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Dec 2010
    Posts
    14
    Thanks
    1

    Default Re: Separating load of GUI and worker thread

    This is the texture generator thread implementation texturegeneratorthread.cpp file. Please bear with me if code snippet is big.

    create_texture is the method where actual computation is done , I call it in the run() method.

    texturegeneratorthread.cpp .....

    Qt Code:
    1. #include "texturegeneratorthread.h"
    2. // #include "half_edge/halfedge.h"
    3. // #include "texture_parameterization/textureparameterization.h"
    4.  
    5. #include <vtkPointData.h>
    6. #include "utility-3d/objwriter.h"
    7. #include "atlas_generation/halfedgedatabuilder.h"
    8. #include "vtkTriangle.h"
    9.  
    10. namespace tr
    11. {
    12.  
    13. TextureGeneratorThread::TextureGeneratorThread()
    14. {
    15.  
    16. #ifdef TR_WINDOWS
    17. directory_separator = "\\";
    18. #endif
    19.  
    20. #ifdef TR_UNIX
    21. directory_separator = "/";
    22. #endif
    23.  
    24. texture_mapper = new TextureMapper();
    25.  
    26. atlas_generator = new AtlasGenerator();
    27. mesh = vtkPolyData::New();
    28.  
    29. texture_image_name = "texture.jpg";
    30.  
    31. #ifdef TR_GUI_MODE
    32. connect( atlas_generator , SIGNAL( percentageCompleted( int ) ) , this , SIGNAL( percentageCompleted( int ) ) );
    33. connect( texture_mapper , SIGNAL( percentageCompleted( int ) ) , this , SIGNAL( percentageCompleted( int ) ) );
    34. #endif
    35.  
    36. }
    37.  
    38.  
    39. void TextureGeneratorThread::load_calibration(Calibration_Info* calib_data)
    40. {
    41. calibration = calib_data;
    42. texture_mapper->load_calibration( calib_data );
    43. }
    44.  
    45.  
    46. void TextureGeneratorThread::load_data(vtkPolyData* data)
    47. {
    48.  
    49. mesh->ShallowCopy( data );
    50.  
    51. texture_mapper->load_data( mesh );
    52.  
    53. }
    54.  
    55. void TextureGeneratorThread::set_working_directory(string directory)
    56. {
    57. working_directory = directory;
    58. }
    59.  
    60. string TextureGeneratorThread::get_texture_image_name()
    61. {
    62. return texture_image_name;
    63. }
    64.  
    65. string TextureGeneratorThread::get_texture_image_path()
    66. {
    67. return texture_image_path;
    68. }
    69.  
    70. void TextureGeneratorThread::set_project_name(string name)
    71. {
    72. project_name = name;
    73. }
    74.  
    75.  
    76.  
    77. void TextureGeneratorThread::get_output(vtkPolyData* output)
    78. {
    79. output->ShallowCopy( mesh );
    80.  
    81. cout<<mesh->GetNumberOfCells()<<" "<<mesh->GetNumberOfPoints()<<endl;
    82. }
    83.  
    84.  
    85.  
    86. void TextureGeneratorThread::create_texture()
    87. {
    88.  
    89. // texture_mapper->load_data( mesh );
    90. //
    91. // texture_mapper->remove_invisible_facets();
    92. //
    93. // texture_mapper->get_output( mesh );
    94.  
    95. HalfEdgeData *_half_edge_mesh = new tr::HalfEdgeData();
    96.  
    97. /*_half_edge_mesh->load_mesh( mesh );
    98.  
    99.   _half_edge_mesh->build();*/
    100.  
    101. HalfEdgeData half_edge_data;
    102.  
    103. HalfEdgeDataBuilder builder( *_half_edge_mesh );
    104.  
    105. vtkPolyData *data = mesh;
    106.  
    107. int _num_points = data->GetNumberOfPoints();
    108.  
    109. int nb_vertices = _num_points ;
    110. int nb_facets = data->GetNumberOfCells() ;
    111.  
    112. builder.begin_surface() ;
    113.  
    114. for(int i = 0; i<nb_vertices; i++)
    115. {
    116. double x[ 3 ] ;
    117. // input >> x >> y >> z ;
    118. data->GetPoint( i , x );
    119.  
    120. builder.add_vertex( Point3d( x[ 0 ] , x[ 1 ] , x[ 2 ] ) ) ;
    121. }
    122.  
    123. vtkIdList *cell = vtkIdList::New();
    124.  
    125. for( int i = 0; i < nb_facets; i++)
    126. {
    127. int nb ;
    128.  
    129. builder.begin_facet() ;
    130.  
    131. data->GetCellPoints( i , cell );
    132.  
    133. nb = cell->GetNumberOfIds();
    134.  
    135. if ( nb == 3 )
    136. {
    137. int v1 = cell->GetId( 0 );
    138. int v2 = cell->GetId( 1 );
    139. int v3 = cell->GetId( 2 );
    140.  
    141. if ( v1 == v2 || v2 == v3 || v3 == v1 )
    142. {
    143. continue;
    144. }
    145.  
    146. double pt1[ 3 ] , pt2[ 3 ] , pt3[ 3 ];
    147.  
    148. data->GetPoint( v1 , pt1 );
    149. data->GetPoint( v2 , pt2 );
    150. data->GetPoint( v3 , pt3 );
    151.  
    152. double area = vtkTriangle::TriangleArea( pt1 , pt2 , pt3 );
    153.  
    154. if ( area == 0 )
    155. {
    156. continue;
    157. }
    158.  
    159. }
    160. else
    161. {
    162. continue;
    163. }
    164.  
    165.  
    166. for(int j = 0; j < nb; j++)
    167. {
    168. int p = cell->GetId( j ) ;
    169.  
    170. builder.add_vertex_to_facet(p) ;
    171. }
    172.  
    173. builder.end_facet() ;
    174.  
    175. }
    176.  
    177. builder.end_surface() ;
    178.  
    179. emit percentageCompleted(5);
    180.  
    181. //atlas_generator->set_half_edge_mesh( _half_edge_mesh );
    182.  
    183. atlas_generator->set_initial_percentage( 0.05 );
    184.  
    185. // TextureParameterization *_parameterizer = new TextureParameterization();
    186.  
    187. // _parameterizer->load_data( _half_edge_mesh );
    188.  
    189. vtkPolyData *_parameterized_mesh = vtkPolyData::New();
    190.  
    191. // _parameterizer->get_output( _parameterized_mesh );
    192.  
    193. atlas_generator->set_half_edge_mesh( _half_edge_mesh );
    194.  
    195. atlas_generator->apply();
    196.  
    197. std::vector< bool > _is_border_facet;
    198. std::vector< char > _opposite_vertex;
    199.  
    200. atlas_generator->get_output( _parameterized_mesh , _is_border_facet , _opposite_vertex );
    201.  
    202. texture_mapper->set_initial_percentage( 0.55 );
    203.  
    204. texture_mapper->load_data( _parameterized_mesh , _is_border_facet , _opposite_vertex);
    205.  
    206. // std::string _texture_image_path = working_directory + directory_separator + texture_image_name;
    207.  
    208. texture_image_path = working_directory + directory_separator + project_name + ".jpg";
    209.  
    210. std::string obj_file_path = working_directory + directory_separator + project_name + ".obj";
    211.  
    212. texture_mapper->create_texture_image2( texture_image_path );
    213.  
    214. texture_mapper->get_output( mesh );
    215.  
    216. ObjWriter *writer = new ObjWriter();
    217.  
    218. writer->set_file_name( obj_file_path );
    219.  
    220. writer->set_input( mesh );
    221.  
    222. writer->write();
    223.  
    224. delete writer;
    225.  
    226. std::cout<<" texture generation completed "<<std::endl;
    227.  
    228. emit percentageCompleted( 100 );
    229.  
    230. }
    231.  
    232. void TextureGeneratorThread::run()
    233. {
    234. emit started();
    235. create_texture();
    236. emit completed();
    237. }
    238.  
    239.  
    240.  
    241. }
    242.  
    243. #include "texturegeneratorthread.moc"
    To copy to clipboard, switch view to plain text mode 


    Here is the header texturegeneratorthread.h ....

    Qt Code:
    1. #ifndef TEXTUREGENERATORTHREAD_H
    2. #define TEXTUREGENERATORTHREAD_H
    3.  
    4. #include "texturemapper.h"
    5. #include "QThread"
    6. #include "calibration_info.h"
    7. #include "vtkPolyData.h"
    8. #include "atlas_generation/atlasgenerator.h"
    9. #include "string"
    10.  
    11. namespace tr{
    12.  
    13. class TextureGeneratorThread : public QThread
    14. {
    15. Q_OBJECT;
    16.  
    17. TextureMapper *texture_mapper;
    18.  
    19. AtlasGenerator *atlas_generator;
    20.  
    21. Calibration_Info *calibration;
    22.  
    23. vtkPolyData *mesh;
    24.  
    25. std::string directory_separator;
    26.  
    27. std::string working_directory;
    28.  
    29. std::string texture_image_name;
    30.  
    31. std::string project_name;
    32.  
    33. std::string texture_image_path;
    34.  
    35.  
    36. protected:
    37.  
    38. void create_texture();
    39.  
    40.  
    41. public:
    42.  
    43. TextureGeneratorThread();
    44.  
    45. void load_calibration( Calibration_Info *calib_data );
    46.  
    47. void load_data( vtkPolyData *data );
    48.  
    49. void set_working_directory( std::string directory );
    50.  
    51. std::string get_texture_image_name();
    52.  
    53. std::string get_texture_image_path();
    54.  
    55. void set_project_name( std::string name );
    56.  
    57. void get_output( vtkPolyData *output );
    58.  
    59.  
    60.  
    61. void run();
    62.  
    63. signals:
    64.  
    65. void started();
    66. void percentageCompleted(int);
    67. void completed();
    68.  
    69. };
    70.  
    71. }
    72.  
    73. #endif // TEXTUREGENERATORTHREAD_H
    To copy to clipboard, switch view to plain text mode 


    Thanks

    Avanindra Singh
    Attached Files Attached Files

  4. #4
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Separating load of GUI and worker thread

    Hmmm no wonder you're app is unresponsive.
    You're creating the thread but never start the event loop in it.

    call exec() at the bottom of the TextureGeneratorThread::run() and remove both emits from there.
    Thread will emit started() signal automatically and instead of emitting finished() yourself, call quit() when you're done.

    Also you're loading meshes before starting the thread. My gut feeling is that loading and processing meshes is quite intensive so I would made the thread to that as well.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Separating load of GUI and worker thread

    Quote Originally Posted by Spitfire View Post
    Hmmm no wonder you're app is unresponsive.
    You're creating the thread but never start the event loop in it.
    I don't think that's it. You don't have to have an event loop if you're not processing events. And the OP is not processing events. Maybe the architecture is not the best one in the world but since the thread IS started and no slots are being called from within the thread, the GUI thread should remain responsive. Of course provided that mesh loading is not the part making the GUI thread unresponsive.

    @avanindra: By the way -- this is usually a useful lecture in such situations: [wiki]Keeping the GUI Responsive[/wiki]
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Dec 2010
    Posts
    14
    Thanks
    1

    Default Re: Separating load of GUI and worker thread

    Thanks for the replies. The problem was occurring due to setting the priorities of the threads. I had set some of the worker threads priorities to QThread::TimeCriticalPriority and this was hampering the responsiveness of the GUI.

    @spitfire

    Thread will emit started() signal automatically and instead of emitting finished() yourself, call quit() when you're done.
    I wrote this code at time when I started learning about Qt Thread API , I emitted these unnecessary signals. nevertheless , these were not the responsiveness hampering codes.


    @wysota
    Thanks for the link . It was really helpful.



    Regards

    Avanindra Singh.

  7. #7
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Separating load of GUI and worker thread

    I'm giving this link constantly: http://labs.qt.nokia.com/2010/06/17/...oing-it-wrong/
    Another thing is that you problem is so common that there is ready solution for it, you should use Qt Concurrent API see: http://qt-project.org/doc/qt-4.8/thr...oncurrent.html , this is quite easy to use and application scales it self without problems.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Separating load of GUI and worker thread

    Quote Originally Posted by MarekR22 View Post
    Ok Marek, but in this exact case the OP's construction is valid and correct one. Not the simplest one as one could use QRunnable or just QtConcurrent::run() but having an event loop in this particular situation would not have changed anything as the only thing the thread does is that it performs an intensive calculation and then quits immediately.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. QTimer in a worker thread
    By inger in forum Newbie
    Replies: 6
    Last Post: 2nd November 2012, 12:37
  2. Replies: 3
    Last Post: 20th September 2011, 20:13
  3. Worker thread
    By doggrant in forum Newbie
    Replies: 4
    Last Post: 3rd November 2009, 15:49
  4. Worker thread problem
    By hkvm in forum Qt Programming
    Replies: 4
    Last Post: 6th September 2009, 20:12
  5. Main thread - worker thread communication.
    By kikapu in forum Newbie
    Replies: 25
    Last Post: 23rd May 2007, 22:09

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
  •  
Qt is a trademark of The Qt Company.