WishhhMaster
Messages postés327Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention10 avril 2010
-
7 févr. 2007 à 12:33
WishhhMaster
Messages postés327Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention10 avril 2010
-
12 févr. 2007 à 06:38
Bonjour,
J'ai un petit problème lié au cross threading. Dans mon application, l'utilisateur choisit divers fichiers images, dont les miniatures sont ensuite affichées dans une listview. Le problème, c'est que dans le cas où il y a beaucoup d'images à afficher, cela prend pas mal de temps. J'utilise donc un bakgroundworker pour mettre les images dans une imagelist (DoWork) , et quand c'est finit j'ajoute les images dans ma listview (RunWorkerCompleted). Je devrais donc éviter l'erreur "cross thread operation not valid", qui arrive quand un control est modifié par un thread autre que celui qui l'a crée.
Ca marche effectivement la premiere fois, mais la 2e fois qu'on choisit les images à afficher, il y a l'erreur. Ca me dit que le control lsv_minipcts est modifié par un thread autre que celui qui l'a crée. Le truc bizarre, c'est que dans le débugger VS, ça pointe sur un endroit où je n'appelle pas lsv_minipcts, mais mon image list. Je pense que en fait les 2 deviennent "connectés" après avoir ajouter les items dans la listview.
Je ne sais pas si c'est clair, donc voilà un petit bout de code:
// imglst: imagelist
//tabstream : un tableau de stream
//filenames: un tableau de string
// bkgwk_openfiles: mon backgroundworker
// lsv_minipcts: ma listview
private void bkgwk_openfiles_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < filenames.Length; i++)
{
// on crée un stream pour chaque fichier
tabstreams[i] = new FileStream(filenames[i], FileMode.Open, FileAccess.Read);
// on ajoute l'image à la listview à partir du stream
imglst.Images.Add(filenames[i], Image.FromStream(tabstreams[i])); // ERREUR ICI
}
}
private void bkgwk_openfiles_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
for (int i = 0; i < filenames.Length; i++)
lsv_minipcts.Items.Add(filenames[i], Path.GetFileName(filenames[i]), filenames[i]);
// on ajoute l'item correspondant à l'image
}
J'espère que c'est plus clair. Utiliser Invoke ou BeginInvoke n'a pas l'air de marcher non plus. Si quelqu'un a une solution...
WishhhMaster
Messages postés327Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention10 avril 20108 12 févr. 2007 à 06:38
J'ai finalement gardé ma solution, mais au lieu de créer directement les miniatures moi-même, je les lis dans les données EXIF des fichiers (pour ceux qui en contienent). C'est beaucoup plus rapide.
LUDINSKI
Messages postés441Date d'inscriptionmardi 2 décembre 2003StatutMembreDernière intervention22 mai 20127 7 févr. 2007 à 13:54
Salut WishhMaster,
Si l'erreur ne se produit que la deuxième fois, je pense que le problème vient du fait que tu ne désalloues pas la mémoire prise par le fichier source (le FileStream que tu mets dans un tableau)
Essayes comme ceci :
private void
bkgwk_openfiles_DoWork(
object
sender, DoWorkEventArgs e )
{
// Parcourt les flux précédemment créés
for
(
int
i = 0; i < tabstreams.Length; i ++ )
{
// Referme le flux en cours
if
( tabstreams[ i ] !=
null
)
tabstreams[ i ].Close();
}
WishhhMaster
Messages postés327Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention10 avril 20108 8 févr. 2007 à 02:42
Salut Ludinski,
Ca ne marche toujours pas. Je désallouais déjà la mémoire ailleurs de toute façon, mais j'avais oublié de le préciser .
Je pense que l'erreur vient du fait que l'imagelist est "liée" à la listview, et donc accéder à l'imageliste dans le DoWOrk du backgroundworker accède à la listview, d'où l'exception.
Voilà le code modifier, avec le Close() pour les streams.
private void bkgwk_openfiles_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < filenames.Length; i++)
{
// on crée un stream pour chaque fichier
tabstreams[i] = new FileStream(filenames[i], FileMode.Open, FileAccess.Read);
// on ajoute l'image à la listview à partir du stream
imglst.Images.Add(filenames[i], Image.FromStream(tabstreams[i])); // ERREUR ICI
// on ferme le stream
tabstreams[i].Close();
}
}
private void bkgwk_openfiles_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
for (int i = 0; i < filenames.Length; i++)
lsv_minipcts.Items.Add(filenames[i], Path.GetFileName(filenames[i]), filenames[i]);
// on ajoute l'item correspondant à l'image
}
Si quelqu'un a une autre façon de faire pour charger des miniatures d'images dans une listview sans que ce soit trop lent et que ça ne bloque pas l'interface utilisateur...
Merci :)
WishhhMaster
Messages postés327Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention10 avril 20108 9 févr. 2007 à 23:56
J'ai réussi à trouver une solution en créant un 2è thread qui ajoute les images crées dans le 1er à mon imagelist. Mais c'est lennnnnnt. J'ai essayé avec le reportprogress du backgroundworker: après chaque
création de 10 images, je les ajoute à la listview mais ça ne marche
toujours pas...
Personne n'a une autre idée pour que mon truc marche? (créer les images, les mettre dans l'imagelist puis ajouter les éléments à la listview sans que l'application freeze?) Le plus long, c'est la création des images, pas l'ajout dans la listview en lui-même.
Merci