Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

[C#] OPÉRATIONS CROSS THREADS - UTILISATION DES DELEGATIONS SYNCHRONES / ASYNCHRONES


Information sur le tutorial

Catégorie :Applications Tutorial .NET ( DotNet ) Date de création : 05/07/2005 14:17:12 Vu : 35 617 fois

Note :
9,3 / 10 - par 20 personnes
9,30 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (26)
Ajouter un commentaire et/ou une note


Description

Ce tutorial explique comment réaliser des modifications inter-threads.

Tutorial

Opérations cross-threads - utilisation des délégations synchrones / asynchrones

 

En.Net, les opérations cross-threads sont interdites. Cela signifie qu'un Thread ne peut modifier les propriétés d'objet qu'un autre Thread a créé.
Prenons par exemple, un Thread qui voudrait modifier la valeur d'un label d'une IHM.

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace

CrossThreadOp
{
   public class MainForm : Form
   {
      private Thread t;
      private Label labelTest;

      public
MainForm()
      {
         InitializeComponent();
         t =
new Thread ( new ThreadStart (ThreadMethod));
         t.Start();
       }

      private
void InitializeComponent()
      {
         this .labelTest = new System.Windows.Forms. Label ();
         this .labelTest.AutoSize = true ;
         this .labelTest.Location = new System.Drawing. Point (29, 23);
         this .labelTest.Size = new System.Drawing. Size (106, 13);
         this .labelTest.Text = "Label avant opération" ;
         this .Controls.Add( this .labelTest);
     }

      private void ThreadMethod()
      { 
          labelTest.Text =
"Label après opération" ;
      }

      public
static void Main()
      {
         Application .Run( new MainForm ());
      }
   }
}

La méthode du Thread (ThreadMethod) se charge seulement de changer le label inclus dans la Form principale.

Vous allez me dire, où se trouve le problème ? Compilé avec le framework.Net 1.x, cet exemple marche parfaitement. En effet, mais il ne s'en trouve pas moins que c'est "techniquement pas beau". Pire encore, compilé avec le Framework 2.0, une exception de typeInvalidOperationException est levée.
Que faire pour solutionner ce problème ? Utiliser des délégations synchrones ou asynchrones.



Définitions synchrone / asynchrone

Un appel est dit synchrone lorsque le thread qui a réalisé cet appel attend que la méthode soit terminée avant de reprendre la main. Ceci implique donc un blocage du thread. 
Dans le cadre d'un appel asynchrone, la méthode appelée rend la main immédiatement, sans que celle-ci soit forcément terminée.
De plus nous n'avons pas à nous préoccuper de quel thread exécute une méthode. C'est le pool de threads qui gère ceci.


3 méthodes vont nous être utiles pour effectuer ces délégations: Control.Invoke(delegate, object[]) dans le cadre d'une délégation synchrone et le couple Control.BeginInvoke(delegate,object[]) / Control.EndInvoke(IAsyncResult) dans le cadre d'une délégation asynchrone.
A noter que sur le framework 2.0, il existe les méthodes Control.Invoke(delegate) et Control.BeginInvoke(delegate), à utiliser quand on a pas de paramètre a passer.


Pour appeler une méthode de manière synchrone ou asynchrone, il nous suffit de référencer cette méthode dans un délégué ayant la même signature que celle-ci, et d'utiliser une des 2 fonctions citées ci-dessus. 

Utilisation de la méthode Control.Invoke   

Nous pouvons utiliser Control.Invoke lorsque le délégué ne retourne pas de valeur et surtout quand les instructions invoquées sont courtes, car la méthode Invoke effectue un appel synchrone ce qui veut dire qu'elle est bloquante. Ce "blocage" va se faire au niveau du thread que nous avons créé. Cela implique que toutes les instructions se trouvant après l'appel de la méthode Invoke seront exécutée une fois seulement la méthode appelée par le délégué terminée.
Dans le cas de notre programme de test, nous allons créer une méthode qui se charge simplement de changer la valeur du Label

private void ChangeLabelText( string str)
{
   labelTest.Text = str;   
}

 Ensuite, créons le délégué correspondant 

        private delegatevoidChangeLabel(string str);

 L'utilisation de la méthode Invoke s'effectue ainsi, dans la méthode ThreadMethod 

       this.Invoke(newChangeLabel(ChangeLabelText), "Label après opération");


Listing complet du programme modifié:  

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace
CrossThreadOp
{
   public class MainForm : Form
   {
      private Thread t;
      private Label labelTest;
      private delegate void ChangeLabel ( string str);

      public MainForm()
      {
         InitializeComponent();
         t =
new Thread ( new ThreadStart (ThreadMethod));
         t.Start();
      }

      private void ChangeLabelText( string str)
      {
         labelTest.Text = str;
         //Thread.Sleep(2000);
      }

      private
void ThreadMethod()
      {
         this .Invoke( new ChangeLabel (ChangeLabelText), "Label après opération" );
         //les instuctions se trouvant ici seront appelées
         //une fois la méthode ChangeLabelText executée et terminée.
         MessageBox .Show( "Invoke terminé" );
      }

      private
void InitializeComponent()
      {
         this .labelTest = new System.Windows.Forms. Label ();
         this .labelTest.AutoSize = true ;
         this .labelTest.Location = new System.Drawing. Point (29, 23);
         this .labelTest.Size = new System.Drawing. Size (106, 13);
         this .labelTest.Text = "Label avant opération" ;
         this .Controls.Add( this .labelTest);
      }

      public static void Main()
      {
         Application .Run( new MainForm ());
      }
   }
}


  Pour démontrer que la méthode Invoke est bloquante, il suffit de décommenter l'instruction « Thread.Sleep(2000) ; » se trouvant dans la méthode ChangeLabel. L'instruction MessageBox.Show() suivant  l'appel à Invoke sera exécutée après 2 secondes.


Utilisation de la méthode Control.BeginInvoke  

Contrairement à la méthode  Invoke, la méthode BeginInvoke s'utilise quand on attend une valeur de retour de la part de notre méthode et/ou quand on souhaite que les instructions la suivant soient appelées immédiatement. L'appel de la méthode BeginInvoke s'effectue, rappelons-le, de façon asynchrone.

Pour tester ceci, nous allons simplement effectuer le chargement d'un tableau de string depuis le Thread principal, et retourner le nombre de strings chargées, que l'on affichera dans un MessageBox. (Bon d'accord, cela ne sert à rien vu qu'on connaît dès le départ le nombre de chaines dans le tableau. Mais c'est juste pour l'exemple).
La valeur de retour de l'appel asynchrone peut être récupérée à l'aide de la méthode EndInvoke. 

Nous déclarons ici la méthode LoadStringArray(string[]), qui retourne la longueur du tableau passé en paramètre, ainsi que le délégué LoadArray(string[]). 

private delegate int LoadArray(string[] array);
privateint LoadStringArray(string[] array)
{
   return array.Length;   
}

 Ajoutons maintenant ces lignes dans notre méthode ThreadMethod :

      string[] values = newstring[]{ "aaa", "bbb","ccc", "ddd"};
      IAsyncResult ias = this.BeginInvoke(newLoadArray(LoadStringArray), newobject[] { values});
      int count = (int)this.EndInvoke(ias);
      MessageBox.Show(count.ToString());


Rien de très compliqué. La première ligne crée le tableau de strings que nous passerons en paramètre.
A la seconde ligne, nous voyons que la méthode BeginInvoke retourne un objet de type AsyncResult.
Nous le passons, à la 3eme ligne, en argument a la méthode EndInvoke, pour pouvoir identifier l'appel asynchrone et récupérer le nombre de valeurs chargées.
Pour finir, nous affichons le résultat à la quatrième ligne.
Magique, le MessageBox affiche la valeur 4, il s'agit bien du nombre de strings que le tableau comprend.

Il est important de noter cependant que l'utilisation de la méthode EndInvoke est bloquante. En effet, si nous structurons notre méthode ThreadMethod de cette façon :

private void ThreadMethod()
{
   string[] values = newstring[] { "aaa", "bbb", "ccc", "ddd" };
   IAsyncResultias = this.BeginInvoke(newLoadArray(LoadStringArray), newobject[] { values });
   int count = (int)this.EndInvoke(ias);
   MessageBox.Show(count.ToString());
   this.Invoke(newChangeLabel(ChangeLabelText), "Label après opération");
}

Nous nous apercevons que le changement de valeur du label se fait seulement après l'appel d'EndInvoke (et du MessageBox.Show).

Notons aussi que même si vous n'attendez pas de valeur en retour quand vous appelez BeginInvoke, il est nécessaire d'appeler la méthode EndInvoke pour chaque BeginInvoke dans votre code. Ceci afin que la CLR nettoie proprement le délégué. 


Listing complet du programme modifié:

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace

CrossThreadOp
{
   public class MainForm : Form
   {
      private Thread t;
      private Label labelTest;
      
      public
MainForm()
      {
         InitializeComponent();
         t =
new Thread ( new ThreadStart (ThreadMethod));
         t.Start();
      }

      private delegate void ChangeLabel ( string str);
      private void ChangeLabelText( string str)
      {
         labelTest.Text = str;
       }
      
      private
delegate int LoadArray ( string [] array);
      private int LoadStringArray( string [] array)
      {
         return array.Length;
      }
      
      private
void ThreadMethod()
      {
         string [] values = new string [] { "aaa" , "bbb" , "ccc" , "ddd" };
         IAsyncResult ias = this .BeginInvoke( new LoadArray (LoadStringArray), new object [] { values });
         // toutes les instructions se trouvant entre BeginInvoke et EndInvoke seront appelées sans 
         //attendre que la méthode LoadStringArray soit terminée
         this .Invoke( new ChangeLabel (ChangeLabelText), "Label pendant opération" );
         int count = ( int ) this .EndInvoke(ias);
         // Les instructions se trouvant ici s'executeront une fois la méthode EndInvoke terminée
         MessageBox .Show(count.ToString());
         this .Invoke( new ChangeLabel (ChangeLabelText), "Label après opération" );
      }

      private
void InitializeComponent()
      {
         this .labelTest = new System.Windows.Forms. Label ();
         this .labelTest.AutoSize = true ;
         this .labelTest.Location = new System.Drawing. Point (29, 23);
         this .labelTest.Size = new System.Drawing. Size (106, 13);
         this .labelTest.Text = "Label avant opération" ;
         this .Controls.Add( this .labelTest);
      }
      
      public
static void Main()
      {
         Application .Run( new MainForm ());
      }
   }
}

 
Info : Remonter une erreur qui se produit dans le délégué asynchrone
 
Pour remonter une erreur qui se serait déclenchée lors de l'appel d'un délégué asynchrone, il faut appeler la méthode EndInvoke de l'instance du délégué :
Exemple :
 
publicdelegatevoidMonDelegate();

public
void MethodeDeleguee()
{
   thrownewException();
}

public
void CallDelegate()
{
   try
   {
      MonDelegate monDel = MethodeDeleguee;
      IAsyncResult iar = monDel.BeginInvoke(null, null);
      monDel.EndInvoke(iar);
   }
   catch (Exception ex)
   {
      MessageBox
.Show(ex.ToString());
   }
}
 
 


Avec ces exemples vous savez maintenant comment utiliser facilement les méthodes Invoke et BeginInvoke.
Vous trouverez ici un exemple utilisant cette technique avec une ProgressBar.
Vous pouvez aussi jeter un ½il à la source de coq, en relation avec le sujet de ce tutorial, et aussi à un article sur le sujet dans la MSDN.
05 juillet 2005 14:33:26 :
ajustements de présentation
05 juillet 2005 16:59:01 :
Diverses modifications
06 juillet 2005 08:21:13 :
Ajout des espaces disparus
24 novembre 2005 17:50:45 :
Petite info .NET 2
01 décembre 2005 21:21:46 :
Rajout d'espaces manquants...
28 février 2006 23:00:48 :
Petite correction
01 mars 2006 10:17:22 :
Enième remise en forme...
01 mars 2006 10:26:32 :
...
09 juin 2006 13:18:40 :
Info concernant le rattrapage d'erreur
09 juin 2006 13:33:19 :
Colorisation du code
12 novembre 2006 10:18:05 :
Ajout d'un lien
signaler à un administrateur
Commentaire de sebmafate le 06/07/2005 06:24:55 administrateur CS

très bien !!!
par contre, faudrait revoir la mise en page, il manque parfois des espaces (sous ie)

signaler à un administrateur
Commentaire de MorpionMx le 06/07/2005 08:14:06 administrateur CS

Merci beaucoup :)
Je vais regarder pour les espaces manquants. J'en ai deja corrigé une bonne poignée, mais j'ai du en louper encore plein.

signaler à un administrateur
Commentaire de Bidou le 07/07/2005 20:31:22 administrateur CS

Vive Mx ;-)
C'est un bon tutorial, bravo.

signaler à un administrateur
Commentaire de MorpionMx le 07/07/2005 20:35:41 administrateur CS

Merci Bidou

signaler à un administrateur
Commentaire de el_teedee le 20/07/2005 09:28:38

Ca c bien cool, moi qui avais du mal à comprendre les delegate. Alors en plus, maintenant je sais la différence entre invoke et begininvoke...

:)

signaler à un administrateur
Commentaire de georgeduke le 29/11/2005 19:18:32

Oui, ça fait plaisir de trouver un tuto comme ça juste quand on en a besoin ! Bravo les explications sont très claires.

signaler à un administrateur
Commentaire de georgeduke le 01/12/2005 21:12:45

Par contre chez moi ça pose probleme au moment de la compilation sur l'invoke :
this.Invoke(new ChangeLabel(ChangeLabelText),"Label après opération");

C'est le deuxieme argument ("Label après opération") qui semble poser problème, apparemment impossible pour lui de convertir le string en object[]...

J'utilise sharpdevelop et .NET 1.1 ; une explication ?

signaler à un administrateur
Commentaire de MorpionMx le 01/12/2005 21:19:52 administrateur CS

ca passe chez moi, en .net 2
Essaie this.Invoke(new ChangeLabel(ChangeLabelText, new String[] { "Label apres operation" }); pour voir

signaler à un administrateur
Commentaire de georgeduke le 01/12/2005 21:23:12

Woaw merci pour ta réactivité ! Effectivement avec cette syntaxe ça passe !

Bizarre, je pensais que la conversion se faisait implictement même en .NET 1.1

Enfin c'est génial ça marche ! :-)

signaler à un administrateur
Commentaire de MorpionMx le 01/12/2005 21:24:23 administrateur CS

Pas de quoi.
Et merci pour ton commentaire :)

signaler à un administrateur
Commentaire de babboss le 14/02/2006 02:57:03

Salut,
Trés bien ce tuto :)
Mais j'aimerai savoir comment adapter cette technique pour appeler un evenement dans une class. Je ne vois pas trop comment faire :/
Peut etre en indiquant à la class la form qui l'apelle. Comme sa elle pourrait automatiquement appeler Invoke sur l'Event. Mais c'est un peut compliquer.
Il n'y a pas une methode plus simple pour appeler une fonction dans le Thread Principal a partir d'un autre thread ?

signaler à un administrateur
Commentaire de med_alpa le 17/02/2006 19:38:53

merci pour votre aide

signaler à un administrateur
Commentaire de gomoz le 01/04/2006 05:29:54

Super ce tuto :)

je crois que j'ai tout compris. Juste une chose quand même : est-ce qu'on peut utiliser un delegate pour plusieurs fonctions demandants le même nombre de paramettre ou est-ce que c'est à eviter ? Et dans la même optique : si jamais on voulais faire simple (juste comme ca pour le fun^^), on pourrait pas réduire le code (ça fais quand même beaucoup lignes là... j'imagine même pas le bordel avec plusieurs tread imbriqués :s).

signaler à un administrateur
Commentaire de sebmafate le 01/04/2006 06:07:53 administrateur CS

tu peux utiliser le même delegate pour plusieurs appel de méthodes ayant le même nombre et les mêmes types de paramètres.

signaler à un administrateur
Commentaire de woot6768 le 31/05/2006 15:35:41

Superbe ton tuto!
Woot

signaler à un administrateur
Commentaire de z_san le 20/07/2006 11:22:51

bravo pour le tuto!
Je voulais écrire un nouveau sujet mais il y a un problème avec l'interface...
j'ai un probleme du même genre, avec un timercallback.
j'ai un service qui, lorsqu'il démarre, lance un timer qui toutes les 15 secondes, appelle le callback (delegate) qui lance ma fonction "CheckUsers".
Dans ma classe (le service) j'ai une hashtable avec des utilisateurs (clef:nom, object:activeUser).
Les activeUser sont des classes qui comportent le nom, la date du dernier check et le nombre de checks "ratés" (trop tard >15sec).
dans ma fonction appelée par le timer callback, j'aimerais modifier le nb de check ratés et au bout de 3 j'enlève l'utilisateur de la hashtable.
Or il m'est impossible de modifier cette valeur, et je ne sais pas pourquoi...

Merci de votre aide

signaler à un administrateur
Commentaire de ld9474 le 11/01/2007 21:16:43

Bonjour,
tuto des plus interessant cependant il y a un petit truc que je ne saisi pas:
Je suis en train de m'amuser avec les BackgroundWorker qui marchent vraiment très bien. Dans le gestionnaire d'évènement DoWork, je fais quelques modifs sur des contrôles du WinForm. Pour le TreeView, je suis obligé de passer par les délégués pour changer la propriété ImageList. En revanche pour une Combobox, je peux changer le DataSource sans problème... Pourquoi les comportements sont différents d'un contrôle à l'autre? Ou alors certaines propriétés peuvent elles être modifiées même dans des threads différents?

signaler à un administrateur
Commentaire de pepedupuis le 21/02/2007 11:59:08

bonjour,
cet exemple marche bien quand la méthode du délégué n'est pas longue. d'apres ce que j'en ai vu c'est finalement pas tres multithread tout ca, puisque la méthode sur le controle est executée dans le thread principal.

je m'explique : dans mon application en 1.1 j'avais un thread secondaire qui permettait un rafraichissement de treeview non bloquant, cette action prenant pas mal de temps. je pouvais continuer a cliquer sur des boutons de l'appli pour faire d'autres actions.
en 2.0 et en utilisant la méthode des delegués je me retrouve avec une appli bloquée...

de meme, dans votre exemple, si dans la méthode  ChangeLabelText( string  str) vous faites une boucle qui incremente un compteur sur le champ avec un ptit sleep pour faire durer et bien impossible de faire autre chose en meme temps sur le formulaire.

avec ce genre d'interdiction de crossthread impossible de paralleliser des taches d'ihm???

qq'un voit une solution ? bien entendu en restant 1.1 compatible
merci de votre aide

signaler à un administrateur
Commentaire de MorpionMx le 21/02/2007 12:37:17 administrateur CS

C'est bien du MultiThread car la méthode est appelée depuis un autre Thread que le Thread principal (celui de l'UI) via la délégation.

Pour la question sur le Thread.Sleep dans une boucle, Thread.Sleep va etre executé dans le Thread de l'UI, et donc bloquer ce Thread (ce qui va creer un blocage de l'UI par la meme occasion).
Si on appele la méthode contenant le Thread.Sleep avec la méthode Invoke (Synchrone), on bloquera aussi le Thread appelant (puisqu'il va attendre que la méthode se termine, et si on fait une longue boucle contenant Thread.Sleep, on risque d'attendre longtemps). Cependant, si on appele cette méthode avec BeginInvoke (en Asynchrone donc), le Thread appelant continuera de s'executer (mais le Thread de l'UI lui continuera d'etre bloqué jusqu'a la fin de la boucle).

J'espere que cette petite explication est claire. C'est assez facile de s'y perdre.
Si tu as une question plus spécifique aux problemes que tu peux rencontrer dans ton application, pose la plutot sur le forum :)

Mx

signaler à un administrateur
Commentaire de pepedupuis le 21/02/2007 14:50:00

au risque d'insister, remplacons le Thread.Sleep par une boucle for qui ne fait rien si ce n'est simuler un traitement lourd, et bien l'application est bloquée de la meme facon.
je l'ai repris l'exemple ci dessus en ne modifiant que la méthode ChangeLabelText( string  str)
pour simuler un traitement lourd avec une boucle vide. bien evidement cette boucle pourrait etre posé dans la méthode du thread auquel cas ca marche mieux mais la n'est pas le but, le but est bien de simuler un traitement lourd dans le delegué (j'ai supprimer l'aspect designer aussi).
et bien bon courage pour ecrire dans le textbox...

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace
CrossThreadOp
{
    public class MainForm : Form
    {
        private Thread t;
        private Label labelTest;

        public MainForm()
        {
            InitializeComponent();
            t = new Thread(new ThreadStart(ThreadMethod));
            t.Start();
        }

        private delegate void ChangeLabel(string str);
        private void ChangeLabelText(string str)
        {
            for (int i = 0; i < 100000; i++)
            {
                labelTest.Text = i.ToString();
                labelTest.Refresh();
            }
        }

        private delegate int LoadArray(string[] array);
        private int LoadStringArray(string[] array)
        {
            return array.Length;
        }

        private void ThreadMethod()
        {
            
            // toutes les instructions se trouvant entre BeginInvoke et EndInvoke seront appelées sans
            //attendre que la méthode LoadStringArray soit terminée
            this.Invoke(new ChangeLabel(ChangeLabelText), "Label pendant opération");
    
        }

        private void InitializeComponent()
        {
            this.labelTest = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            //
            // labelTest
            //
            this.labelTest.AutoSize = true;
            this.labelTest.Location = new System.Drawing.Point(29, 23);
            this.labelTest.Name = "labelTest";
            this.labelTest.Size = new System.Drawing.Size(110, 13);
            this.labelTest.TabIndex = 0;
            this.labelTest.Text = "Label avant opération";
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(32, 195);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(218, 20);
            this.textBox1.TabIndex = 1;
            //
            // MainForm
            //
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.labelTest);
            this.Name = "MainForm";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        public static void Main()
        {
            Application.Run(new MainForm());
        }

        private TextBox textBox1;
    }
}


signaler à un administrateur
Commentaire de pepedupuis le 21/02/2007 14:58:35

et ma question reste la meme :
avec ce genre d'interdiction de crossthread impossible de paralleliser des taches d'ihm???

(c'est a dire pouvoir utiliser l'ihm pendant un rafraichissement lourd d'une partie de l'ihm compatible 1.1 et 2.0 sans avoir a tout repeter le code)

signaler à un administrateur
Commentaire de MorpionMx le 21/02/2007 15:01:06 administrateur CS

Oké, j'ai compris ce que tu voulais dire.
Mais cela n'a aucun sens. Le code que tu nous montre là revient au meme que de ne lancer aucun Thread (tu lances un Thread qui va executer un traitement lourd dans le Thread principal). C'est ton nouveau Thread qui doit faire ce traitement lourd ! (ce qui est le but justement de créer un nouveau Thread)...Et il doit simplement indiquer le changement de valeur au label.
Il faut donc mettre la boucle dans le nouveau Thread, et changer la valeur du label depuis ce Thread via le délégué (et là la TextBox est de nouveau reactive).

signaler à un administrateur
Commentaire de MorpionMx le 21/02/2007 15:05:02 administrateur CS

Et pour répondre a ta question : regarde cet exemple concret
http://www.csharpfr.com/codes/THREAD-PROGRESSBAR-EXEMPLE-SIMPLE_40294.aspx

Le Thread compresse les fichiers, le statut de la progression est indiqué via la ProgressBar, et l'IHM reste tout a fait reactive

signaler à un administrateur
Commentaire de pepedupuis le 21/02/2007 15:59:22

bien sur, ca n'a aucun sens, c bien ce qui me genait

en 2.0 fini les threads qui font et le calcul et le traitement graphique... en qq sorte on ne peut plus faire de "multithread graphique"...

meme si je comprends le concept de l'interdiction crossthread, je dis vive le Control.CheckForIllegalCrossThreadCalls car sinon bonjour la modif de code...

signaler à un administrateur
Commentaire de coq le 11/08/2007 20:04:35 administrateur CS

En somme, vive le masquage de problème.
Le truc c'est surtout qu'en .NET 2.0 on signale le problème qui existait avant mais dont presque personne n'avait réellement conscience.

signaler à un administrateur
Commentaire de grogru le 23/08/2007 10:26:56

A propos des opérations asynchrones dans les WinForms sur PocketPC il faut savoir que les opérations BeginInvoke et EndInvoke n'existent pas dans le Compact Framework 2. Ce qui rend l'application de la méthode expliquée ci-dessus impossible.
Seul solution : gérer ses threads à la main.

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,094 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.