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

C# Discussion :

Quel pattern ou type de thread me conseilleriez vous ?


Sujet :

C#

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut Quel pattern ou type de thread me conseilleriez vous ?
    Bonjour à vous.

    Je commence à avoir l'habitude d'utiliser les backgroundworker, lock et invoke, et d'ailleur je me limite quasiment qu'à ça. Car à chaque fois les threads = plein de problèmes

    Ahh les lock... je les utilisent que si nécéssaire, sur un minimum de ligne de code dont je controle crois controler la durée de vie. J'utilise un minimum de variable de lock, et pourtant malgrès tout des fois ça bloque.

    Bref ... les threads et moi ne faisont pas très bon ménage.

    Alors :
    Aujourd'hui dans mon programme aux millions de lignes de code (j'exagère à peine), je veux placer une methode dans un thread, cette methode est appellée une fois pour initialiser pas mal de choses.

    Et je n'ose pas le faire. Car je sens que des variables vont se paumer d'un thread à l'autre, qu'un event va appeller le control d'une form, bref j'ai peur !

    d'où la question : quel patern ou type de thread me conseilleriez vous? idéalement que ça ait un impact minimum sur mon code???

    Désolé, je me sent mauvais en écrivant tout cela... j'utilise le Framework 3.5

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    332
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2002
    Messages : 332
    Points : 502
    Points
    502
    Par défaut
    Personnellement, je refuse tous les contrats où j'aurais à développer en 3.5. Passe à 4.5 avec C# 5 et utilise la nouvelle approche multi-thread qui a justement été conçue pour minimiser les maux de tête.

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Babyneedle Voir le message
    Personnellement, je refuse tous les contrats où j'aurais à développer en 3.5. Passe à 4.5
    super !
    le conseil inutile de la journée
    tout le monde ne peut pas choisir ses outils de développements
    et puis le framework 3.5 contient déjà tout ce qu'il faut pour faire du multithreading, les apports du 4.5 permettent de gagner un peu de temps en codage mais nécessitent quand même de comprendre le fonctionnement et les locks

    @giova_fr
    un programme mal fait a souvent trop de lignes de code et des enchevêtrements de code qui le rende buggable à la moindre modif
    concernant le multithreading, un variable n'appartient pas à un thread, donc elle ne peux pas se perde, c'est régit par les lois de la portée comme toutes les variables
    donc déjà écrire son code en bonne POO cloisonnée ca aide à éviter les problèmes

    sur les patterns de multithreading il faut comprendre quelles sont les problèmes potentiels et les moyens de les contourner
    - les controles (et les dependencyObject en wpf) ne sont modifiables que depuis le thread les ayant instancié
    il convient donc de demander à ce thread d'appeler le code qu'on souhaite pour faire les modifs (delegate, events du backgroundworker etc...)
    - pour une variable simple sans verrouillage il y a risque de perte de données
    quand on incrémente un entier par exemple il y a une lecture de la valeur, une augmentation de 1 puis un restockage de la valeur
    si 2 threads demandent une incrémentation on risque de perdre une des deux incrémentations, pour ca il y a les incrémentations atomiques
    pour une variable objet, si on instancie l'objet dans une variable publique, puis qu'on remplie ses propriétés, et qu'un autre thread utilise cette variable il risque de l'utiliser avant qu'elle soit finie d'être inialisée, pour ca on peut remplir une variable locale privée puis la placer dans la variable publique à la fin de l'init, l'autre thread a juste à tester si la variable est à null pour attendre avant de l'utiliser
    - pour les collections si un thread fait un for each et qu'un autre thread fait un .add ca plante, pour ca il faut verrouiller

    il y a plusieurs types de verrouillages, le lock, on lock une variable (généralement un new object public), un autre thread demandant le lock de cette variable attendra que le 1er sorte du lock pour continuer
    ca permet donc pour un traitement d'être sur de ce qui se passe
    dans certains cas pour plus de performances il y a le readerwriterlock(|slim)
    il peut y avoir plusieurs lecteurs en même temps (accès à une collection par exemple) mais en cas d'écriture tout le monde attends (.add par exemple)

    exemple d'une propriété singleton en lazy initialization:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    private static object _verrouPourMachin = new object();
     
    private static truc _machin; 
    public static truc machin {
         get {
             if (_machin != null)             return _machin;
             lock (_verrouPourMachin) {
                 if (_machin != null)                 return _machin;
                 _machin = new truc();
                 //initialisation
             }
         }
     }
    le lock fait que potentiellement plusieurs threads sont en attente sur cette ligne, donc juste après on retestes si pas null on return, pour ne pas instancier plusieurs fois et ce retrouver avec des variables perdues et qui ne sont plus uniques du coup

    après il y a d'autres choses, mais c'est selon les besoins, si tu nous en dis plus sur tes problèmes on pourra t'aiguiller vers ce qu'il faut faire ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Merci Pol pour ta réponse détaillée.
    Passe à 4.5
    C'est une appli grand public, et certains utilisateurs sont sous vista (malheureusement). Déjà qu'ils ont la flemme de lire le guide de démarrage qui fait une demie page, alors leur demander de faire un windows update, il ne faut pas compter dessus

    Pol : Réactions à ton post
    concernant ton exemple, à quoi sert la premiere ligne hors du lock?
    pourquoi ne pas mettre directement le lock?

    Ce que je fais en général va je crois dans le même sens que ce que tu as ecris :
    pour les collections, j'utilise readerwriterlockslim.

    Sinon je m'arrange pour que seul un des 2 threads ecrive dans une variable, et je fais systématiquement ceci pour "partager" une variable (continuer dans cet exemple):

    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
     
    bool continuer;
    readonly object _lock = new object();
     
    void ThreadA()
    {
        continuer = true;
        //Demarre threadB();
        Thread.Sleep(1000);
        lock(_lock)
            continuer = false;
    }
     
       void ThreadB()
       {
            bool localcontinuer = true;
            while(localcontinuer)
            {
                 //Un peu de boulot
                 lock(_lock)
                     localcontinuer = continuer;
            }
        }
    J'essaye d'avoir un minimum d'objets lock pour éviter les interlock
    je fais des lock ultra court, sans appel à des methodes dont je ne maitrise pas la durée de vie

    Et malgrès tout, des fois ça se fige

    Mes Besoins

    Mes besoins sont on ne peut plus classiques, par exemple j'ai une methode qui dure et je ne veux pas figer l'IHM, j'ouvre une fenetre "veuillez patienter" avec une animation qui rassure l'utilisateur, puis je lance mon thread.

    Un des problèmes c'est qu'on est souvant obligé de passer par une callback. Je déteste les callback/events de thread !
    Comment faire pour que cette callback ne prolonge pas la durée de vie du 2eme thread?
    Comment faire quand on ne veut pas de callback? :
    on veut que la methode appellant le 2eme thread (ThreadA dans mon exemple) soit bloquante sans pour autant figer l'IHM ?

    Je me retrouve à faire des whiles dégueulasses:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while(cabosse && TimeoutDeSecu)
    {
    Thread.Sleep(40);
    Application.DoEvents();
      lock(_lock)
        cabosse= infoDeThreadB;
    }
    if(cabosse)
       throw new TimeOutExcection("blablabla");
    Quand je prévois de faire du multithread dès le début de la conception, ca va.
    Mais quand je veux 6 mois plus tard placer une methode dans un thread, je me retrouve à chercher une solution "anti-callback"
    Car tout le reste du code, s'attend à une methode bloquante, et je ne veux pas qu'une callback crée une fuite de thread (que j'appelle "sommeil éternel du thread principal")

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par giova_fr Voir le message
    concernant ton exemple, à quoi sert la premiere ligne hors du lock?
    pourquoi ne pas mettre directement le lock?
    si tu parles de la ligne avant le lock, c'est parce qu'une fois la variable créé il ne faut bloquer personne pour vérifier son existence, si elle existe on la retourne

    Citation Envoyé par giova_fr Voir le message
    Un des problèmes c'est qu'on est souvant obligé de passer par une callback. Je déteste les callback/events de thread !
    Comment faire pour que cette callback ne prolonge pas la durée de vie du 2eme thread?
    Comment faire quand on ne veut pas de callback? :
    on veut que la methode appellant le 2eme thread (ThreadA dans mon exemple) soit bloquante sans pour autant figer l'IHM ?
    le principe normal c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    button.click
      démarrer thread
      showdialog patientez
     
    voidthread
      traitement
      invoke fin traitement
     
    fin traitement
        fermer fenetre showdialog
    moi les méthodes avec callback du framework que je connais elles sont des méthodes synchrones aussi
    dans ce cas dans le thread on appelle les méthodes synchrones
    si tu en as trouvés sans méthodes synchrones je veux bien savoir lesquelles
    enfin dans ce cas il suffit de modifier le schéma de la sorte je pense

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    button.click
      démarrer thread
      showdialog patientez
     
    voidthread
      traitement
      mthAsync(callback)
     
    callback
      suite traitement si nécessaire
      invoke fin traitement
     
    fin traitement
      fermer fenetre showdialog
    un callback étant appelé sur le thread qui l'a appelé

    Citation Envoyé par giova_fr Voir le message
    Je me retrouve à faire des whiles dégueulasses
    en effet ^^
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Encore merci, c'est vraiment sympa de ta part !

    Qu'entends tu par mthAsync?

    Et les invoke, ok c'est super, mais invoke c'est dans une form
    Ca veut dire qu'une fenetre en plus du role d'afficher et interagir avec l'utilisateur, doit rapatrier l'execution dans le thread principale. Pas génial non?

    Enfin des fois mon histoire de thread se passe dans une assembly n'ayant pas de référence vers windows form. Ou bien une classe qui n'a aucun rapport avec une form, pourtant ses methodes sont appellée dans le thread principale (et du coup figent l'HIM). Exemple improvisé :

    [Monprogramme.exe]
    KeyboardListener.SpaceBarPressed =>
    [MaGestionMultimedia.dll]
    MonGestionnaire.StartPlaySansThread =>
    [LibrairieTiers.dll]
    TiersMP3Player.Play
    Tout cela se passe totalement hors du contexte d'une Form, et SpaceBarPressed s'est executé dans le thread principale.Donc l'HIM est figé jusqu'à ce que Play retourne.

    Je veux donc déplacer une partie de l'execution dans un thread :

    [Monprogramme.exe]
    KeyboardListener.SpaceBarPressed =>
    [MaGestionMultimedia.dll]
    MonGestionnaire.StartThreadPlay =>
    [LibrairieTiers.dll]
    Play =>callbackPlayed
    comment faire un invoke? KeyboardListener , MonGestionnaire, et la librairieTiers ne connaissent pas de Form. Ca n'est pas leur role...

  7. #7
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    pour des cas ou le code est déporté (et c'est tant mieux ^^) il faut faire justement comme dans le framework, des méthodes asynchrones avec callback

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private Action<bool> _callback;
     public void Traitement(Action<bool> callback) {
         _callback = callback;
         // start thread
     }
     
      private void thread() {
         //traitement
         _callback.Invoke(true);
     }
    et côté form :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    button.click
      instancier la classe qui gère le traitement
      instance.Traitement (fintraitement)
     
     
    fintraitement(boolean result)
       me.invoke { if bool == true msgbox ok }
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    okkk !

    il y a 2 jours encore, je ne connaissais pas Action

    donc

    _callback.Invoke

    résout mon problème de CallBack qui ne s'execute pas dans le thread principale !

    Ca me fait un sacré problème stress en moins !

    Bon il y a encore pas mal de choses qui ne sont pas clairs dans mon esprit j'essayerai de faire un topic un peu moins vaste sur le sujet...

  9. #9
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    pour résumer, sur le thread principal avant d'afficher un message d'attente, on demande à une méthode d'une classe de faire le truc
    on lui dit quelle méthode appeler quand c'est fini (il n'y a pas qu'action qui va ici, il y a delegate, et d'autres classes de callbacks (iasyncresult et autres))
    la méthode en question stocke la méthode à appeler, elle démarre un thread, fait le traitement puis le thread appelle le callback
    le callback se retrouve donc ici sur le thread non UI il faut alors que l'écouteur du callback invoke

    en wpf on peut faire mieux simplement, ce sont les dispatcher (maitre d'un thread) qui peuvent invoker, donc sans controle on peut invoker sur un autre thread
    on stockerait alors au départ le dispatcher appelant (currentdispatcher) pour l'utilisant dans le thread pour appeler le callback
    ca doit être possible en windows forms car des classes du framework y arrivent je crois (appeler un callback sur le thread de départ) mais je n'ai pas vraiment regardé comment
    (enfin ca serait encore plus pratique, ca évite l'invoke à la fin sur le form)
    on a bien le currentthread, mais on ne peut pas faire .invoke sur un thread (à la différence d'un dispatcher de wpf)

    après moi dans ces cas là je ne m'embete pas, si je suis sur que ma classe sera utilisée dans un exe windows forms je fais
    openforms(0).invoke
    le callback est donc bien appelé sur le thread principal
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Merci, je tag le topic en résolu, mais je reviendrai surement, je donnerai alors un bon exemple concis et précis.

    Car pour les invokes tout me semble clair maintenant, mais je redoute toujours l'effet d'une fuite de thread (callback jamais appellée) je le sais, ça va m'arriver

  11. #11
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    J'ai trouvé des infos concernant delegate.Invoke (je ne parle pas de Control.Invoke bien connu de tous).

    J'esperai naivement, que si le delegate était instancié dans le thread de la form, alors appeller Invoke dessus ferait s'executer la callback dans le thread principal :

    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
     
    MaForm : Form
    {
       Task _callback;
       public MaForm()
       {
            _callback = new Task(ChangerText);
       }
     
       void ChangerText()
       {
             label.Text = DateTime.Now.ToString();
       }
     
       void backgroundWorker_DoWork(object sender,DoWorkEventArgs e)
       {
           _callback.Invoke(); //espoir naif :)
       }
    }
    Or il n'en est rien, on obtient le classique opération inter-thread non valide

    Alors j'ai voulu comprendre le role de delegate.Invoke, et j'ai trouvé cette explication :
    The difference is in performance and benefits. If you directly call a method then the compiler will generate the necessary code to look up the method start address in the object's virtual table, push the parameters onto the stack and invoke the method. The runtime is ultimately responsible for dealing with this because a vtable can change depending on the object being used. Highly optimized and very fast given modern processors. This is the ideal mechanism to use. The problem is that you must know at compilation time the type being referenced, the method name and its signature. This is formally known as early binding. If the method information changes then your code won't compile. Normally this is no problem but sometimes it is important. This is where invoke comes in.
    Donc on en revient à ce que je disais, obliger de donner à une Form le role de garde fou pour etre sur que la callback s'execute dans le thread principal...

  12. #12
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par giova_fr Voir le message
    mais je redoute toujours l'effet d'une fuite de thread (callback jamais appellée) je le sais, ça va m'arriver
    si c'est bien codé aucun risque
    traitement
    try catch, dans le catch throw pour que l'appelant sache qu'il y a une erreur avant appel du thread
    dans la méthode du thread faire un try catch avec dans le catch un appel du callback avec un booléen pour dire que c'est pas bon (ou alors un appel dans le finally avec un booléen déclaré avant le try)


    Citation Envoyé par giova_fr Voir le message
    J'ai trouvé des infos concernant delegate.Invoke (je ne parle pas de Control.Invoke bien connu de tous).
    le delegate a été inventé avant le action, il n'est pas super utile de nos jours car moins pratique

    Citation Envoyé par giova_fr Voir le message
    Donc on en revient à ce que je disais, obliger de donner à une Form le role de garde fou pour etre sur que la callback s'execute dans le thread principal...
    en effet c'est illogique dans la conception, mais comme je disais il me semble que le framework y arrive, il faudrait donc regarder comment il fait
    j'essaierais ce soir pour voir si j'y arrive
    et il reste la solution du openform[0].invoke qui marche plutot bien
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #13
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    j'ai fini par trouver la classe magique utilisée dans le framework
    ci dessous le code qui permet de faire de l'asynchronisme avec callback appelé sur le thread utilisé au moment du createoperation (donc le thread principal dans notre cas)

    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
     
    public class Form1
    {
     
     
        private void Form1_Click(object sender, System.EventArgs e)
        {
            c t = new c();
            t.Traitement(fin);
        }
     
        private void fin(bool result)
        {
            this.Text = "fin";
        }
        public Form1()
        {
            Click += Form1_Click;
        }
     
    }
     
     
    public class c
    {
     
        private System.ComponentModel.AsyncOperation operationContext;
     
        private Action<bool> _callback;
        public void Traitement(Action<bool> callback)
        {
            try {
                _callback = callback;
                operationContext = System.ComponentModel.AsyncOperationManager.CreateOperation(null);
                System.Threading.Thread th = new System.Threading.Thread(TraitementAsync);
                th.Start();
            } catch (Exception ex) {
                throw;
            }
        }
     
        private void TraitementAsync()
        {
            try {
                System.Threading.Thread.Sleep(2000);
                // traitement
     
                operationContext.Post(new System.Threading.SendOrPostCallback(() => _callback.Invoke(true)), null);
            } catch (Exception ex) {
                operationContext.Post(new System.Threading.SendOrPostCallback(() => _callback.Invoke(false)), null);
            }
        }
     
     
    }
    d'ailleurs msdn dit à propos de cette classe magique que
    les gestionnaires d'événements sont appelés sur un thread ou un contexte qui est approprié pour le modèle d'application (par exemple, les applications Windows Forms, les applications ASP.NET, les applications console, etc.).
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  14. #14
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Merci mille fois !
    Je venais justement pour parler à ce sujet.

  15. #15
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Après moultes investigations, je réalise que BackgroundWorker utilise justement SynchronisationContext, c'est ce qui lui permet d'avoir la callback JobDone executée dans le thread de l'UI (celui qui l'a instancié).

    Malheureusement pour moi, tout cela ne sert à rien. Car une grande partie de mon code s'execute dans des plugins qui sont dans des AppDomain différents.

    Or SynchronizationContext n'est pas sérialisable, du coup mes plugins ne peuvent pas se synchroniser avec le thread de l'UI

    Je vais donc me fabriquer ma propre classe utilisée dans l'AppDomain principale et qui gère la synchro. Je ne sais pas encore comment je vais organiser tout ça ...

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

Discussions similaires

  1. [Conception] quel est le type de variable a choisir?
    Par King_T dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 29/05/2006, 00h27
  2. [conception] quel pattern choisir?
    Par r0d dans le forum C++
    Réponses: 4
    Dernier message: 26/04/2006, 18h56
  3. Quel est le type retourné ?
    Par Rupella dans le forum C
    Réponses: 4
    Dernier message: 30/11/2005, 14h01
  4. [langage] "@$" Quel est ce type de variable?
    Par YanK dans le forum Langage
    Réponses: 4
    Dernier message: 21/04/2005, 18h07
  5. Réponses: 1
    Dernier message: 26/03/2004, 14h14

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