IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Multithreading Discussion :

Mise à jour de la progression d'une tâche


Sujet :

Multithreading

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut Mise à jour de la progression d'une tâche
    Bonjour,

    Je vous explique mon petit problème

    J'ai une liste contenant une grande quantité de messages:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::deque<ProviderMessage*> pending_;
    Et j'ai une classe Logic avec une méthode processMessages() qui se simplifie en:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    void Logic::processMessages()
    {
      // Connect the addQuote signal to the addQuote slot to update GUI
      QObject::connect( this,    SIGNAL( addQuote(const timestamp_t&, const price_t&, const quantity_t&, const price_t&, const quantity_t&) ),
                        quotes_, SLOT  ( addQuote(const timestamp_t&, const price_t&, const quantity_t&, const price_t&, const quantity_t&) ) );
      // Connect the addTrade signal to the addTrade slot to update GUI
      QObject::connect( this,    SIGNAL( addTrade(const timestamp_t&, const price_t&, const quantity_t&) ),
                        trades_, SLOT  ( addTrade(const timestamp_t&, const price_t&, const quantity_t&) ) );
      // Connect the progress signal to the logicProgress slot to update the progress bar
      QObject::connect( this,        SIGNAL( progress     (datetime_t) ),
                        simulation_, SLOT  ( logicProgress(datetime_t) ) );
     
      // For each pending message
      std::deque<ProviderMessage*>::iterator it = pendingMessages_.begin();
      for (; it!=pendingMessages_.end(); ++it )
      {
        // Emit message to update GUI
        switch ( (*it)->type() )
        {
          case ProviderMessage::QUOTE:
          {
            const QuoteItem* quote = static_cast<const QuoteMessage*>(*it)->quote();
            // Update GUI
            emit addQuote( quote->timestamp(),
                           quote->bidPrice(), quote->bidQuantity(),
                           quote->askPrice(), quote->askQuantity() );
            // Update progress
            emit progress( quote->timestamp() );
            break;
          }
          case ProviderMessage::TRADE:
          {
            const TradeItem* trade = static_cast<const TradeMessage*>(*it)->trade();
            // Update GUI
            emit addTrade( trade->timestamp(), trade->price(), trade->quantity() );
            // Update progress
            emit progress( trade->timestamp() );
            break;
          }
        }
      }
      pendingMessages_.clear();
    }
    Le signal progress(datetime_t) est connecté à un slot logicProgress qui met à jour une barre de progression.
    Les signaux addX() sont connectés à des modèles (des dérivés de QAbstractListModel) pour ajouter l'item et les visualiser dans des vues.

    Cette méthode processMessages() est lancée dans un thread séparé du principal.

    Si je commente les émissions de signaux d'update de la GUI ( addX() ) tout se passe bien: la barre de progression est mise-à-jour fréquemment.
    Mais lorsque ces signaux sont envoyés, c'est comme si tous mes signaux de progress étaient relayés la fin de la pile des signaux. La barre de progression n'avance plus, jusqu'à ce que processMessage finisse et la *boum* ma barre de progression saute à 100%.

    Je me doute que je n'ai pas du respecter/comprendre quelquechose avec les signaux
    Ils sont pourtant bien sensés être ordonnés par ordre d'envoi ?

  2. #2
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Après quelques tatonnements, ce qui semble causer le souci, c'est le slot d'ajout de données dans les modèles.

    Voici leur forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void TradeListModel::addTrade( const timestamp_t& timestamp, const price_t& price, const quantity_t& quantity )
    {
      beginInsertRows( QModelIndex(), 0, 0 );
     
      items_.push_front( new TradeItem(timestamp, price, quantity) );
     
      endInsertRows();
    }
    Plus particulièrement, ce sont les beginInsertRows/endInsertRows qui causent le problème.

  3. #3
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Je viens de batcher les envois de messages, l'update de la GUI et de la progression se fait maintenant tous les 100 messages (plutot qu'à chaque message)

    Ca donne donc quelquechose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    void Logic::processMessages()
    {
      QObject::connect( this,    SIGNAL( addQuotes(const QuoteList&) ),
                        quotes_, SLOT  ( addQuotes(const QuoteList&) ) );
     
      QObject::connect( this,    SIGNAL( addTrades(const TradeList&) ),
                        trades_, SLOT  ( addTrades(const TradeList&) ) );
     
      QObject::connect( this,        SIGNAL( progress     (datetime_t) ),
                        simulation_, SLOT  ( logicProgress(datetime_t) ) );
     
      // Size of messages sent to the GUI to batch updates
      const static unsigned int batch_size = 100;
     
      QuoteList quoteList;
      TradeList tradeList;
     
      std::deque<ProviderMessage*>::iterator it = pendingMessages_.begin();
      for (; it!=pendingMessages_.end(); ++it )
      {
        switch ( (*it)->type() )
        {  
          case ProviderMessage::QUOTE:
          {
            const QuoteItem* quote = static_cast<const QuoteMessage*>(*it)->quote();
     
            quoteList << quote;
     
            if ( quoteList.size() >= batch_size )
            {
              emit progress( quote->timestamp() );
              emit addQuotes( quoteList );
              quoteList.clear();
            }
     
            break;
          }
          case ProviderMessage::TRADE:
          {
            const TradeItem* trade = static_cast<const TradeMessage*>(*it)->trade();
     
            tradeList << trade;
     
            if ( tradeList.size() >= batch_size )
            {
              emit progress( trade->timestamp() );
              emit addTrades( tradeList );
              tradeList.clear();
            }
     
            break;
          }
        }
      }
     
      if ( quoteList.size() > 0 )
      {
        emit addQuotes( quoteList );
        quoteList.clear();
      }
     
      if ( tradeList.size() > 0 )
      {
        emit addTrades( tradeList );
        tradeList.clear();
      }
     
      pendingMessages_.clear();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void TradeListModel::addTrades( const TradeList& list )
    {
      beginInsertRows( QModelIndex(), 0, list.size()-1 );
     
      for (TradeList::const_iterator it = list.begin(); it!=list.end(); ++it )
        items_.push_front( new TradeItem( (*it)->timestamp(), (*it)->price(), (*it)->quantity() ) );
     
      endInsertRows();
    }
    Certes l'update est plus rapide, mais ca n'a rien changé au problème du _lag_ de mise-à-jour de la progress bar

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par NewbiZ Voir le message
    Certes l'update est plus rapide, mais ca n'a rien changé au problème du _lag_ de mise-à-jour de la progress bar
    C'est a dire?

  5. #5
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Par update, je veux dire le temps de mise-à-jour des QListView.
    100 ajouts de 1 million d'items, sont plus rapides que 100 millions d'ajouts d'1 item.

    Je pense que le problème, c'est que ce qui prend du temps, ce n'est pas le dispatch que je fais dans le processMessages(), c'est l'insertion des items dans les modèles (et la mise-à-jour des vues). Et bien que l'appel de ces méthodes d'ajout soient passées par signaux depuis le thread de calcul, elles se font dans le thread principal de GUI, ce qui a pour conséquence la lenteur de rafraichissement de la barre de progression, et la perte de réponse des widgets.

    Enfin, ce n'est que la conclusion que j'en tire, je ne connais pas assez Qt pour l'affirmer.

    Si c'est ca, ca me pose un souci, puisque j'imagine (s'il vous plait détrompez moi ) que les widgets Qt ne peuvent pas être updatés directement depuis un autre thread que le principal.
    La question deviendrait donc "comment ajouter d'énormes quantités de données dans des widgets Qt sans que la GUI perde en réactivité".

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par NewbiZ Voir le message
    Enfin, ce n'est que la conclusion que j'en tire, je ne connais pas assez Qt pour l'affirmer.
    Je pense que c'est bien cela. 1 million d'item cela commence a faire pas mal.

    Citation Envoyé par NewbiZ Voir le message
    Si c'est ca, ca me pose un souci, puisque j'imagine (s'il vous plait détrompez moi ) que les widgets Qt ne peuvent pas être updatés directement depuis un autre thread que le principal.
    exactement


    Citation Envoyé par NewbiZ Voir le message
    La question deviendrait donc "comment ajouter d'énormes quantités de données dans des widgets Qt sans que la GUI perde en réactivité".
    En faite, cela dépend fortement de ce qu'affiche ta view. Par contre je suis etnné qu'il dit faire un update globale. Normalement le *view sont optimisé et ne s'occupe que des item ce qui sont affiché. Je vien de voir que tu fait items_.push_front. Es ce que faire un push_back est embêtant?
    Es ce que c'est nécessaire d'updater le treeview aussi souvent?

    Il me semble que c'est le endInsertRows(); qui provoque l'update. Peut être faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    beginInsertRows( QModelIndex(), 0, list.size()-1 );
    avant le premier ajout
    et
    aprés le dernier ajout

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VBA-E]Mise à jour de cellule alimentée par une liste
    Par moritan dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 19/01/2007, 06h11
  2. mise à jour de la valeur d'une liste
    Par nicolovitch dans le forum Access
    Réponses: 4
    Dernier message: 03/08/2006, 13h20
  3. Réponses: 1
    Dernier message: 24/04/2006, 16h16
  4. Mise à jour de données à partir d'une autre table
    Par rsc dans le forum Langage SQL
    Réponses: 7
    Dernier message: 05/04/2006, 10h53
  5. Probleme de mise à jour et de modification d'une base
    Par flambo88 dans le forum Requêtes
    Réponses: 17
    Dernier message: 07/12/2005, 14h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo