none
Assigner un thread pour une classe singleton RRS feed

  • Question

  • Bonjour,

    je développe une application qui utilise des modules externes sous formes de plugin.

    J'ai aussi une classe singleton que me permet de gérer les dialogues avec mes plugins.

    Le dialogue avec les plugins peuvent prendre beaucoup de temps et je souhaiterais allouer un Thread qui s'occupera de toutes les transactions avec mes plugins.

    Je souhaiterais savoir comme faire cela :

    Public Class PluginInstanceManager

            Public Shared ReadOnly Property Instance As PluginInstanceManager
                Get
                    If oInstance Is Nothing Then oInstance = New PluginInstanceManager
                    Return oInstance
                End Get
            End Property
            Private Shared oInstance As PluginInstanceManager

            Private Sub New()
               'Ici démarrage du thread (ou pas)
            End Sub

            Public Sub Method1()
               'Appelant le thread pour l'exécution
            End Sub

            Public Sub Method2()
               'Appelant le thread pour l'exécution
            End Sub

    ...

    End Class

    Toutes vos idées sont les bienvenues.

    Merci de votre aide.


    • Modifié Fiko81 lundi 8 décembre 2014 16:56
    lundi 8 décembre 2014 16:56

Réponses

  • Bonjour,

    D'accord je comprends mieux vos contraintes. Alors en effet TAP n'est pas d'une grande utilité dans votre cas (quoique).

    En fait vous avez besoin d'un "Scheduler", c'est à dire un objet qui exécute une suite d'action les une après les autres dans un thread spécifique sans qu'elles se chevauchent sous peine d'avoir un interblocage.

    Regardez ce projet https://github.com/ygrenier/tests/tree/master/TestAsync

    c'est un projet de test que j'ai modifié pour mieux coller à votre problématique.

    L'idée est de créer une tâche dite LongRunning (elle sera créée dans un thread séparé) qui va regarder dans une pile s'il y a des actions à exécuter. L'objet ActionManager fourni des méthodes permettant d'empiler des actions à exécuter.

    Le tout est synchronisé pour éviter les interblocages.

    L'exemple WPF montre comment on peut exécuter des méthodes de différentes manières (avec attente ou pas).

    Le tout utilise la TPL car c'est plus simple à manipuler qu'un thread et des contextes de synchronisation.

    Cordialement,


    Yan Grenier


    • Proposé comme réponse Yan Grenier - MTFC vendredi 12 décembre 2014 09:34
    • Modifié Yan Grenier - MTFC vendredi 12 décembre 2014 09:36 Aie plein de fautes ;)
    • Marqué comme réponse Fiko81 vendredi 12 décembre 2014 12:29
    vendredi 12 décembre 2014 09:34

Toutes les réponses

  • Bonjour,

    Au lieu d'utiliser des threads, pourquoi ne pas utiliser le Task-based Asynchronous Pattern? C'est le modèle idéal pour votre cas il me semble, mais il faut que la version du Framework.net soit 4.5 minimum.

    Le principe du TAP c'est une faire retourner des tâches que l'on attend éventuellement à la fin.

    Petit exemple en C# :

    public Task DoSomething()
    {
       return Task.Run(()=>
       {
          //Des fonctions qui prennent du temps...
       });
    }

    Et pour l'utilisation :

    Task tsk = DoSomething();
    
    //Faire peut-être d'autres traitements pendant ce temps...
    
    //et à la fin
    await tsk;

    Désolé, je ne savais plus comment ça s'écrivait en VB.NET, ça fait un moment que je n'en ai plus fait... lol

    Cela dit, attention aux méthodes qui utilisent des éléments d'IHM : elles doivent se faire sur le même thread.


    Philippe

    mardi 9 décembre 2014 15:25
  • Bonsoir,

    Merci pour cette réponse.

    J'ai jeté un oeuil à la définition du TAP. Je ne suis pas sure de ce que je vais dire mais il me semble que cela ne me garantit pas que Method1 et Method2 soit exécuté dans le même thread.

    Or j'ai vraiement besoin de garantir que toute mes méthodes de ma classe utilisent le même thread.

    Merci.

    mercredi 10 décembre 2014 20:22
  • Bonjour,

    Pourquoi c'est une nécessité d'utiliser le même thread ?

    Ce que vous voulez faire implique de mettre en place des mécanismes de synchronisation pas toujours simple à créer (sans compter la gestion des erreurs), de synchroniser vos appels car votre thread ne peut faire qu'une seule chose à la fois, si vous avez un résultat à renvoyer il faut mettre en place des verrous, etc...

    L'intérêt du TAP est d'encapsuler toute cette complexité, de plus vos différents appels sont considérés comme une tâche autonome, et si l'une des tâches prend X secondes, vous pouvez toujours exécuter une autre tâche (qui sera exécutée quand le système aura les ressources disponibles en fonction de la machine sur laquelle il s'exécute).

    A moins d'avoir de gros problèmes de performance, a l'heure actuelle on ne préoccupe pas trop du/des threads que l'on exploite, le TAP nous fournis les outils nécessaires pour résoudre la majorité des problèmes de multitâche et de s'adapter à la machine en cours d'exécution.

    Cordialement,


    Yan Grenier

    jeudi 11 décembre 2014 07:19
  • Bonjour Fiko81,

    D'après le modèle que vous nous aviez montré plus haut, c'est exactement le même principe que le TAP : Dans le TAP, une méthode renvoie un objet qui est la procédure en cours d'exécution : il faut bien distinguer la procédure qui renvoie la tâche et la tâche elle-même. La seule différence entre ce que vous nous avez montré et le TAP c'est que dans votre cas aucun objet n'est retourné. Or, je pense qu'il peut être intéressant justement d'avoir la tâche en question car elle peut être utilisée pour vous synchroniser.

    Pour illustrer tout cela, l'exemple que je vous ai montré plus haut peut être présenté un peu différemment :

    public Task LaMethodeAsync()
    {
       return Task.Run(LaMethode);
    }
    private void LaMethode()
    {
       //Le traitement bien long...
    }

    ...et ainsi, dans vos traitement, vous avez même la possibilité de savoir si le traitement asynchrone est terminé ou pas.

    Autre chose aussi : en reprenant l'exemple plus haut il faut bien noter cela :

    private async void UnHandler(object sender, EventArgs arg)
    {
       //Ici on est dans le thread de l'IHM...
    
       await LaMethodeAsync();
    
       //Quand on arrive ici, on revient dans le même thread que l'IHM!!!
    }
    
    private async void UnAutreHandler(object sender, EventArgs arg)
    {
       //Ici on est dans le thread de l'IHM...
    
       await LaMethodeAsync().ConfigureAwait(false);
    
       //Par contre quand on arrive ici on est dans le même thread que celui de l'objet Task renvoyé par LaMethodeAsync()
    }

    Cela est plutôt bien expliqué dans la doc MSDN...


    Philippe

    jeudi 11 décembre 2014 08:12
  • Bonsoir,

    J'ai besoin de travailler sur le même thread car ma classe PluginInstanceManager gère les instances de mes plugins et donc les objets de connections Hardware qu'ils nécessitent. Le soucis est que ces objets de connections ne peuvent être utilisés qu'avec le thread qui en crée l'instance.

    Ces objets de connections sont instanciés une première fois au démarrage de l'application et détruits à la fermeture. Entre les deux, il peux se passer un millier de commandes qui arrive de différents thread que je dois router sur le même thread qui en a créé l'instance. Actuellement, j'utiliser le thread de l'interface :

    Application.Current.Dispatcher.Invoke(...)
     

    Le soucis est que ceci me bloque très régulièrement mon interface. J'imagine qu'il existe une solution pour éviter d'utiliser le thread de l'interface pour faire ce travail.

    J'espère que ces explications sont claires.

    Merci.

    Fiko81.

    jeudi 11 décembre 2014 22:01
  • Bonjour,

    D'accord je comprends mieux vos contraintes. Alors en effet TAP n'est pas d'une grande utilité dans votre cas (quoique).

    En fait vous avez besoin d'un "Scheduler", c'est à dire un objet qui exécute une suite d'action les une après les autres dans un thread spécifique sans qu'elles se chevauchent sous peine d'avoir un interblocage.

    Regardez ce projet https://github.com/ygrenier/tests/tree/master/TestAsync

    c'est un projet de test que j'ai modifié pour mieux coller à votre problématique.

    L'idée est de créer une tâche dite LongRunning (elle sera créée dans un thread séparé) qui va regarder dans une pile s'il y a des actions à exécuter. L'objet ActionManager fourni des méthodes permettant d'empiler des actions à exécuter.

    Le tout est synchronisé pour éviter les interblocages.

    L'exemple WPF montre comment on peut exécuter des méthodes de différentes manières (avec attente ou pas).

    Le tout utilise la TPL car c'est plus simple à manipuler qu'un thread et des contextes de synchronisation.

    Cordialement,


    Yan Grenier


    • Proposé comme réponse Yan Grenier - MTFC vendredi 12 décembre 2014 09:34
    • Modifié Yan Grenier - MTFC vendredi 12 décembre 2014 09:36 Aie plein de fautes ;)
    • Marqué comme réponse Fiko81 vendredi 12 décembre 2014 12:29
    vendredi 12 décembre 2014 09:34
  • Bonjour,

    Je ne me rendais pas compte de la difficulté de mon exercice :).

    Merci en tout cas pour cet exemple que je vais ajuster dans mon application. C'est exactement ce qu'il me faut.

    Merci beaucoup.

    vendredi 12 décembre 2014 12:30