Cross thread problème [Résolu]

WishhhMaster 327 Messages postés mardi 17 février 2004Date d'inscription 10 avril 2010 Dernière intervention - 7 févr. 2007 à 12:33 - Dernière réponse : WishhhMaster 327 Messages postés mardi 17 février 2004Date d'inscription 10 avril 2010 Dernière intervention
- 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...

Merci :)
Afficher la suite 

Votre réponse

4 réponses

Meilleure réponse
WishhhMaster 327 Messages postés mardi 17 février 2004Date d'inscription 10 avril 2010 Dernière intervention - 12 févr. 2007 à 06:38
3
Merci
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.

Merci WishhhMaster 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 125 internautes ce mois-ci

Commenter la réponse de WishhhMaster
LUDINSKI 441 Messages postés mardi 2 décembre 2003Date d'inscription 22 mai 2012 Dernière intervention - 7 févr. 2007 à 13:54
0
Merci
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();
    }


    for
(
int
i = 0; i < filenames.Length; i ++ )
    {

        // on crée un flux pour chaque fichier


        tabstreams[ i ] = new FileStream(....

Dis-moi ce qu'il en ait !
Commenter la réponse de LUDINSKI
WishhhMaster 327 Messages postés mardi 17 février 2004Date d'inscription 10 avril 2010 Dernière intervention - 8 févr. 2007 à 02:42
0
Merci
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 :)
Commenter la réponse de WishhhMaster
WishhhMaster 327 Messages postés mardi 17 février 2004Date d'inscription 10 avril 2010 Dernière intervention - 9 févr. 2007 à 23:56
0
Merci
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
Commenter la réponse de WishhhMaster

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.