none
MTAThread dans une application WPF RRS feed

  • Discussion générale

  • Bonjour,

    après de multiples recherches sur internet, je ne trouve pas comment faire fonctionner mon code.

    En effet, au lancement de ma fenêtre, j'ai plusieurs méthodes qui interagissent avec la base de données avant de lancer le résultat de ces méthodes (List) dans une méthode.

    Pour augmenter la rapidité, je voudrais créer plusieurs threads pour la récupération des données :

     

        private void ReloadCalendar()
        {
          // Load private events
          List<Event> pList = new List<Event>();
          List<Event> uList = new List<Event>();
          List<Event> cList = new List<Event>();
          List<Event> tList = new List<Event>();
          List<Event> fList = new List<Event>();
    
          AutoResetEvent[] waitHandles = new AutoResetEvent[]
          {
            new AutoResetEvent(false),
            new AutoResetEvent(false),
            new AutoResetEvent(false),
            new AutoResetEvent(false),
            new AutoResetEvent(false)
          };
    
          ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
          {
            pList = BllEvents.FetchAllPrivateEventsByUser(CurrentUser.id, Timetableasy.Tools.Calendar.StartDate, Timetableasy.Tools.Calendar.StopDate);
            waitHandles[0].Set();
          }));
    
          ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
          {
            uList = BllEvents.FetchAllUniversityEvents(Timetableasy.Tools.Calendar.StartDate, Timetableasy.Tools.Calendar.StopDate);
            waitHandles[1].Set();
          }));
    
          if (CurrentUser.isAdmin || CurrentUser.isCampusManager)
          {
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
            {
              cList = BllEvents.FetchAllCampusEvents(Timetableasy.Tools.Calendar.StartDate, Timetableasy.Tools.Calendar.StopDate);
              waitHandles[2].Set();
            }));
          }
    
          if (CurrentUser.isTeacher)
          {
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
            {
              tList = BllEvents.FetchAllTeacherEvents(CurrentUser.id, Timetableasy.Tools.Calendar.StartDate, Timetableasy.Tools.Calendar.StopDate);
              waitHandles[3].Set();
            }));
          }
    
          if (CurrentUser.isStudent)
          {
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
            {
              int campus = (int)CurrentUser.campus;
    
              cList = BllEvents.FetchAllCampusEvents(campus, Timetableasy.Tools.Calendar.StartDate, Timetableasy.Tools.Calendar.StopDate);
              waitHandles[4].Set();
            }));
          }
    
          WaitHandle.WaitAll(waitHandles);
    
          fList.AddRange(pList);
          fList.AddRange(uList);
          fList.AddRange(cList);
          fList.AddRange(tList);
    
          // Refresh events
          MainCalendar.LoadEvents(fList);
        }

     

    Dans une application console tout fonctionne. Dans mon appli WPF j'ai l'erreur suivante : 

    WaitAll for multiple handles on a STA thread is not supported.

    D'après ce que j'ai lu que ce soit en winforms ou en WPF, il faut du STAThread.

     

    Y a t-il une méthode pour faire fonctionner le code ci-dessus ?

     

    Merci d'avance.

     

    Aymeric Lagier

     


    Aymeric Lagier http://www.aymericlagier.com
    lundi 7 juin 2010 14:14

Toutes les réponses

  • Bonjour,

    Je n'arrive pas à reproduire le problème...

    Avez-vous essayé de ce code :

    for(int i=0; i<waitHandles.Length; i++)
    {
      waitHandles[i].WaitOne();
    }

    Cordialement


    Gilles TOURREAU - MVP C# - MCP - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 8 juin 2010 18:41
    Modérateur
  • Bonjour,

     

    merci pour votre réponse.

    C'est étrange que le soucis ne soit pas reproduit chez vous. D'où cela pourrait-il venir ?

    Le problème ne se produit que pour une application WPF et surement Winforms puisque les 2 utilisent STAThread.

    J'ai finalement contourné le problème en lançant un thread qui lance les autre. A la fin je fais donc simplement un waithandle.WaitOne(); pour éviter le WaiAll.

     

    Je suis quand même curieux de connaître le pouquoit du comment.

     

    Merci d'avance


    Aymeric Lagier http://www.aymericlagier.com
    mardi 8 juin 2010 19:57
  • Bonjour,

    Le thread qui fait le WaitAll() est bien le thread WPF ? Avez-vous essayé de faire une boucle de WaitOne() ? Et quelle version de Visual Studio / .NET Framework utilisez vous ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCP - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 8 juin 2010 21:41
    Modérateur
  • Bonjour,

     

    oui oui c'est bien le thread WPF.

    J'ai repris mon code dans un nouveau projet en changeant juste les méthodes accédant à la base de données par de simples ajouts

    J'utilise VS 2010 et .NET 4

     

    Cordialement


    Aymeric Lagier http://www.aymericlagier.com
    jeudi 10 juin 2010 18:47