#1 Le 01/07/2008, à 15:09
- rniamo
traitement lourd, comment avoir de l'intéractivité ? [résolu]
bonjour,
je m'amuse à apprendre le C++ et Gtk-- en faisant un navigateur (en un visualisateur de fichiers pour le moment ).
Ce logiciel a donc besoin d'intéractivité hors pour le moment si j'ai beacoup de fichiers (surtout des images) dans un répertoire, le logiciel est trés long à réagir.
Dans la version actuelle du code, j'ouvre un thread (via gtk--) et je raffrachit la fenetre tous les 10 entités (fichiers, dossier...).
pour l'installation ou récupération des sources :
svn co svn://svn.tuxfamily.org/svnroot/rniamoflow/rniamoflow rniamoflow
PS : il faut gtkglextmm aussi.
edit : j'ai oublié la question : pourquoi il faut attendre longtemps avant que la fenêtre soit raffrachit ?
Dernière modification par rniamo (Le 15/07/2008, à 15:36)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#2 Le 01/07/2008, à 19:07
- robrob
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Un conseil, utilise un outil de profilage (gprof) pour analyser ce qui prend du temps dans ton code.
Hors ligne
#3 Le 01/07/2008, à 20:25
- nicolas.sitbon
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Je n'y connais rien en C++ et GTK-- mais si ça a un quelconque rapport avec C/GTK+, alors il faut éviter les threads et utiliser les gtk_idle().
Dernière modification par nicolas.sitbon (Le 01/07/2008, à 20:25)
Hors ligne
#4 Le 02/07/2008, à 16:47
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
j'utilise "g_idle" (j'appel ça un thread pour simplifier) et je sais où le code est lourd ... mais je ne sais pas comment l'optimiser.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#5 Le 02/07/2008, à 17:00
- nicolas.sitbon
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
D'accord dans ce cas ça n'a pas de rapport direct avec GTK+ mais c'est plus un problème de perf et d'optimisation. Montre ton code si tu le veux bien!
Hors ligne
#6 Le 04/07/2008, à 16:36
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Le problème vient du fait que j'utilse ce constructeur pour chaque fichier (image ou pas) :
Fichier::Fichier(const string& d, const string& n, int t) : dossier(d), nom(n), taille(t)
{
string f;
d!="/" ? f=d+"/"+n : f=d+n;
int status;
struct stat st;
status=lstat(f.c_str(),&st);
if (S_ISREG(st.st_mode))
{
try
{
pixbuf=Gdk::Pixbuf::create_from_file(f,Fichier::TAILLE_PIXBUF,Fichier::TAILLE_PIXBUF,true);
}
catch(Gdk::PixbufError&)
{
pixbuf.reset();
}
catch(Glib::FileError&)
{
pixbuf.reset();
}
}
}
PS : - c'est le pixbuf qui pren du temps...(on s'en doute mais ça va mieux en le disant)
- le code est dispo dans la svn
Dernière modification par rniamo (Le 04/07/2008, à 17:02)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#7 Le 05/07/2008, à 11:48
- robrob
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Si tu veux une interface réactive pendant un traitement lourd, il te faut utiliser des "vrais" threads.
(l'interface reste dans le thread principal, le traitement "lourd" lui est déporté dans le/les thread(s)).
Puisque tu utilises gtkmm, tu as ça pour les threads:
http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/group__Threads.html
Tu peux fonctionner comme ceci:
- Lorsque tu entres dans un répertoire, tu lances un thread qui va prendre en charge le chargement des images. En attendant tu affiches un petit dessin à la place au niveau de ton interface.
- Le thread peut par exemple à chaque nouvelle image chargée, envoyer un message à l'application pour lui indiquer qu'elle peut l'utiliser.
- lorsque toutes les images sont chargées, le thread s'arrête
- lorsque que tu quittes le repertoire, le thread est arrêté (si il tourne encore) puis détruit (pour ce faire le thread doit être "joinable").
Au niveau objet, les images appartiennent à l'application principale, le thread aura pour boulot de mettre à jour l'image et indiquer si l'image est disponible. Cette indication de disponibilité sera évidement protégée par un mutexe.
La seule difficulté me semble être la gestion de la communication de l'information des images chargées. Je ne connais pas les possibilités qu'offre gtk à ce niveau (en wxWidgets j'utilise des événements, c'est très pratique pour ça).
Hors ligne
#8 Le 07/07/2008, à 13:23
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
comment utiliser des sémaphore en gtkmm ?
edit : est-ce que quelqu'un peut m'expliquer un truc que je n'ai jamais compris : quand j'ouvre un thread et que je modifie une variable dans le thread 1, pourquoi celle-ci n'est pas modifiée dans le "thread principal" (via g_idle) ?
edit bis : je répond un peux tard en ce moment car je n'ai plus le net chez moi.
Dernière modification par rniamo (Le 07/07/2008, à 15:56)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#9 Le 07/07/2008, à 18:54
- robrob
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Pour l'edit, essaye de déclarer ta variable en tant que "volatile", par exemple:
volatile int compteur;
Elle permet au compilateur d'indiquer que la variable est susceptible d'être modifier par qqu d'autre et donc d'éviter certaines optimisations.
Pour les mutexes faut que je regarde, je ne connais pas gtkmm
Hors ligne
#10 Le 08/07/2008, à 20:36
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
Merci pour l'edit, je vais tester cela dès que je peux.
Pour le gtkmm, je fais ça dès que j'ai le net plus de 15min .
Merci.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#11 Le 14/08/2008, à 15:26
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
bon je teste actuellement les thread avec gtkmm mais j'ai un soucis :
try
{
thread=Glib::Thread::create(sigc::mem_fun(*this,&ListeCourant::listeDossierEff),true);
thread->join(); // remplace join() par un mutex sur ce qu'il faut ... mais il faut quoi ?
}
catch(Glib::ThreadError& e)
{
cout << e.what() << endl;
}
catch(Glib::Thread::Exit& e) {}
le fait d'appeler join() me fait perdre l'intérêt du thread, il me faut certainement un mutex mais sur quoi ?
voici la "fonction-threadée" :
void ListeCourant::listeDossierEff(void)
{
static Glib::RefPtr<Gdk::Pixbuf> pixF=Gdk::Pixbuf::create_from_file(fen.getTheme()+ICON_FICHIER,TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,true);
static Glib::RefPtr<Gdk::Pixbuf> pixD=Gdk::Pixbuf::create_from_file(fen.getTheme()+ICON_DOSSIER,TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,true);
string repCourant=fen.getCourant();
try
{
Glib::Dir dir(repCourant);
string name=dir.read_name();
int id=0;
while(!name.empty())
{
if (name.length() && name[0] != '.')
{
string path=Glib::build_filename(repCourant,name);
Glib::ustring nom=Glib::filename_to_utf8(name);
if (Glib::file_test(path,Glib::FILE_TEST_IS_DIR))
{
TreeModel::Row row=*(this->refTreeModel->append());
row[this->treeModel.pixbuf]=pixD;
row[this->treeModel.chemin]=repCourant;
row[this->treeModel.nom]=nom;
row[this->treeModel.type]="Dossier";
row[this->treeModel.taille]="";
row[this->treeModel.id]=id++;
Dossier d(nom);
fen.getListeDossier().push_back(d);
fen.getListeDossier().sort(Dossier::tri);
}
else if (Glib::file_test(path,Glib::FILE_TEST_IS_REGULAR) && fichierTmp(path) && formatOK(path))
{
TreeModel::Row row=*(this->refTreeModel->append());
int taille=utile::taille(path);
Fichier f(fen.getCourant(),nom,taille);
if(f.getPixbuf())
{
f.setPixbufIconPetite(f.getPixbuf()->scale_simple(TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,Gdk::INTERP_BILINEAR));
row[this->treeModel.pixbuf]=f.getPixbufIconPetite();
}
else
row[this->treeModel.pixbuf]=pixF;
row[this->treeModel.chemin]=repCourant;
row[this->treeModel.nom]=f.getNom();
row[this->treeModel.type]="Fichier";
if (taille<0)
row[this->treeModel.taille]="";
else if (taille/1048576>0)
row[this->treeModel.taille]=utile::all2string(taille/1048576)+","+utile::all2string(taille-(taille/1048576)*1048576)+" Mo";
else if (taille/1024>0)
row[this->treeModel.taille]=utile::all2string(taille/1024)+","+utile::all2string(taille-(taille/1024)*1024)+" ko";
else
row[this->treeModel.taille]=utile::all2string(taille)+" o";
row[this->treeModel.id]=id++;
fen.getListeFichier().push_back(f);
fen.getListeFichier().sort(Fichier::tri);
}
}
name=dir.read_name();
fen.getGLScene().queue_draw();
}
fen.getGLScene().queue_draw();
}
catch(const Glib::FileError& ex)
{
std::cout << ex.what() << std::endl;
}
// pas de lib de mem si Glib::Thread::Exit();
}
edit : un peu d'aide sue les thread ne serait pas de refus
Dernière modification par rniamo (Le 14/08/2008, à 22:29)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#12 Le 15/08/2008, à 16:40
- rniamo
Re : traitement lourd, comment avoir de l'intéractivité ? [résolu]
bon l'utilisation de gdk_thread_leave/enter marche mais ça fait de grosses modif pour un petit logiciel.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne