[Grand débutant] Programme en tâche de fond trop lourd

jdalbert Messages postés 3 Date d'inscription mercredi 31 janvier 2007 Statut Membre Dernière intervention 21 septembre 2008 - 18 sept. 2008 à 03:27
jdalbert Messages postés 3 Date d'inscription mercredi 31 janvier 2007 Statut Membre Dernière intervention 21 septembre 2008 - 21 sept. 2008 à 22:03
Bonjour,

J'ai fait un programme C# qui vérifie toutes les minutes l'arrivée de nouveaux mails et je voudrais le faire exécuter en tâche de fond, i.e. qui ne soit pas visible à part dans la liste des processus. De plus je ne veux pas que ce programme soit un "service windows".

A la base, j'avais fait un programme console, mais pour ne pas afficher cette console j'ai finalement choisi l'output "Windows Application".
Mais voilà : en mode console, pour empêcher que le programme ne se termine, je faisais Console.ReadLine().
Maintenant que je suis en mode windows application, je ne sais pas trop comment faire cette attente infinie.

J'ai trouvé cette solution de secours :

namespace JMail
{
    class Program
    {
        static void Main(string[] args)
        {
            new Service(); // Ma classe qui check les mails toutes les minutes
            Thread.Sleep(Timeout.Infinite);
        }
    }
}

Je penses pas que ce soit très propre, de plus avec cette solution, le programme utilise 12 mo de mémoire RAM (?!!).
Je voudrais donc connaître une solution propre et peu consommatrice en mémoire pour faire boucler le programme.

Merci d'avance.

5 réponses

billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
18 sept. 2008 à 09:20
Bonjour,

Pour cela, il te suffit de lancer ton service de réception de mail dans un nouveau thread et d'attendre la fin de ce thread avec la méthode Thread.Join().
Urls:
- http://emerica.developpez.com/csharp/threads/
- http://msdn.microsoft.com/fr-fr/library/ms173178(VS.80).aspx
- http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx

Ou sinon, tu peux utiliser la classe AutoResetEvent:
- http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
- Expliqué aussi dans le dernier lien du dessus

Sur ce, bon courage,


Billou_13

Bonne journée,


Billou_13
0
jdalbert Messages postés 3 Date d'inscription mercredi 31 janvier 2007 Statut Membre Dernière intervention 21 septembre 2008
18 sept. 2008 à 13:42
Bonjour billou_13,

Je n'ai pas très bien compris à quoi pourrait me servir la méthode Thread.Join().
Néanmoins j'ai adapté mon programme en mettant, comme tu me l'as conseillé, mon service dans un thread :

class Program
    {
        static void Main(string[] args)
        {
            Thread myThread;
            myThread = new Thread(new ThreadStart(ThreadLoop));
            myThread.Start();
        }

        // Cette méthode est appelée lors du lancement du thread
        static void ThreadLoop()
        {
            Service service = new Service();

            // Boucle pseudo infinie
            while(Thread.CurrentThread.IsAlive)
            {
                // Attente de 1 minute = 60s
                Thread.Sleep(60000);

                service.update(); // mise à jour de mon nombre de mails non lus
            }
        }

    }

Pendant les 60 premières secondes, le programme ne prend que 3-4 mo de mémoire ram. Lors de service.update(), il passe à 12 mo de ram et il y reste ! A la fin de l'update, les objets utilisés sont tous détruits. Je ne comprends pas pourquoi ça ne repasse pas à 3-4 mo de ram.
0
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
18 sept. 2008 à 14:28
A ce niveau, il va falloir regarder ton code dans le update(), il doit y avoir des objets non libéré ou autre. Mais là, je ne peux te dire sans analyse...

Concernant la méthode Thread.Join(), que tu pourrais appeler dans ton code comme ceci:
myThread.Start();
myThread.Join();
Ici la méthode te permet de dire que le code s'arrête à la ligne Join() (donc le thread s'exécute tout seul) et ne continuera qu'après la fin du thread.
Donc, en gros, si tu le rajoute à ton code, la fenêtre de commande (console) devrait rester ouverte et en attente. Alors que je suppose que dans ton exemple, la fenêtre disparait.
Seulement, ton programme ne se termine que lorsque tous les threads sont fermés => d'où le fait que ton programme continue de tourner

Bonne analyse,


Billou_13
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
20 sept. 2008 à 20:43
Salut,


Entre autres, la gestion mémoire en .NET fonctionne avec un garbage collector qui est chargé de libérer la mémoire occupée par les objets qui ne sont plus utilisés.
Il n'effectue pas forcément cette tâche rapidement si la charge de la machine ne le nécessite pas.
Après il faut aussi voir d'autres choses; commele nombre d'assemblies externes qui sont chargées lors du premier appel à la méthode update, etc

/*
coq
MVP Visual C#
CoqBlog
*/
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jdalbert Messages postés 3 Date d'inscription mercredi 31 janvier 2007 Statut Membre Dernière intervention 21 septembre 2008
21 sept. 2008 à 22:03
C'est bien un problème lié au garbage collector (ou autre).

Pour tester, j'ai restreint ma méthode update au strict minimum : se connecter puis se déconnecter tout de suite après.

/* Connexion au serveur pop de gmail par TCP + SSL */
private void connect()
{
    this.tcpClient = new TcpClient(this.serveur, this.port);
    this.fssl = new SslStream(tcpClient.GetStream(), false);
}

/* Déconnexion */
private void disconnect()
{
    this.fssl.Close();
    this.fssl = null;

    this.tcpClient.Close();
    this.tcpClient = null;
}

Lorsque la méthode connect() est appellée, le programme passe de 3 à 8mo de mémoire vive. Après la déconnexion, le programme reste à 8mo de mémoire vive alors que je voudrais qu'il repasse à 3.
0
Rejoignez-nous