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 :

Apparition d'une form tant qu'un process est en cours [Débutant]


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    260
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 260
    Points : 386
    Points
    386
    Par défaut Apparition d'une form tant qu'un process est en cours
    Bonjour bonjour,

    Bon, pour commencer, le c# pour moi, c'est un vieuuuux souvenir et pas grand chose de plus

    Sinon pour mon problème, le voici :

    J'ai une form, form1.cs qui n'a pour le moment que 1 bouton. Ce bouton lance une extraction de données depuis sql server puis en génère un fichier excel. Jusque là, tout va bien.

    Niveau architecture, le onclick de mon bouton va appeler une procédure présente dans une classe nommée "ExportExcelFile". J'ai, dans cette classe, différentes procédures dont celle qui va remplir une datatable et celle qui va écrire le fichier sql se basant sur cette datatable.

    Maintenant, mon but est de montrer à l'utilisateur que l'export est en cours et/ou que l'export est fini. Ainsi, je me suis basé sur le lien suivant :

    https://social.msdn.microsoft.com/Fo...forum=winforms

    J'ai donc fait un windows form tout beau avec le même nom associé.
    Par soucis de praticité, j'ai créé une nouvelle classe "LoadingClass" qui comporte les fonctions que l'on trouve dans le lien.

    J'ai donc, dans ma class ExportExcelFile l'appel suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // Initialisation de la classe du chargement
                LoadingClass LC = new LoadingClass();
                // Gestion du gif de chargement
                LC.StartProgress("Loading...");
    Cependant, je me heurte à quelques soucis... Et internet me perd plus qu'autre chose...


    Déjà, dans ma classe avec les fonctions copiées, j'ai voulu simplifier (en virant la partie Thread, mais quelle erreur...). Je suis donc revenu a un copier/coller assez bête de ce qui se trouve sur le lien

    Cependant, à la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (this.InvokeRequired)
    VS me dit que "LoadingClass ne contient pas de définition pour InvokeRequired" et aucune méthode d'extension accessible 'InvokeRequired' acceptant un premier argument de type 'LoadingClass' n'a été trouvé"


    Alors bon, là pour le coup, je me sens un peu (beaucoup débile)... Si quelqu'un peut être mon saveur divin, je lui ferais un poème et j'embaucherais des bardes pour chanter ses louanges au 4 coins du globes...

    Bisous bisous

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Personnellement, voici comme je fais :

    Je crée une instance d'une classe qui va faire le boulot.
    J'ouvre ma fenêtre d'attente (qui est une fenêtre borderless avec un gros gif animé de sablier qui prend les 3/4 de l'écran) et je lui passe le boulot à faire.
    C'est ensuite cette dernière qui l'exécute, et se ferme dès que le job est terminé.

    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
     
            // Form appelante
            private void BtnDoIn_Click(object sender, EventArgs e)
            {
                FrmWait frmWait = new FrmWait();
     
                ProcessStartInfo psi = new ProcessStartInfo("mmco.exe", string.Format("-u:{0} -p:{1} -k:i,{2},l,q", Properties.Settings.Default.Login, Properties.Settings.Default.Password, Station.Numero))
                {
                    CreateNoWindow = true,
                    WorkingDirectory = string.Concat(Properties.Settings.Default.WinDir, @"\system\exe")
                };
                frmWait.SetPsi(psi);
                frmWait.ShowDialog();
            }
     
     
            // FrmWait
            private ProcessStartInfo Psi;
     
            public void SetPsi(ProcessStartInfo psi)
            {
                Psi = psi;
                Process p = new Process
                {
                    StartInfo = Psi,
                    EnableRaisingEvents = true
                };
                p.Exited += P_Exited;
                p.Start();
            }
     
            private void P_Exited(object sender, EventArgs e)
            {
                Close();
            }
    Ici je passe par un ProcessStartInfo qui tourne dans son propre thread, d'où la complexité du bouzin.

    Sinon, il suffit de faire "job.Run()" dans le load de FrmWait suivi d'un this.Close()

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    260
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 260
    Points : 386
    Points
    386
    Par défaut
    Merci pour ta réponse, je vois (enfin je pense) ce que tu veux faire. Toutefois, techniquement, j'ai l'impression d'être à la ramasse (c'est plus simple le scripting )

    Si possible, j'aurais besoin de quelques petits éclaircissements :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new ProcessStartInfo("mmco.exe", string.Format("-u:{0} -p:{1} -k:i,{2},l,q"
    Le lien du .exe, il correspond à un traitement "interne" à ton projet c#ou à totalement autre chose ?
    Ensuite, si je comprends bien, c'est ton "waiting screen" qui fait le process. Si je le rapporte à mon exemple, mon "waiting screen" lancerait la requête SQL et l'export des données ?

    UPDATE :
    J'ai trouvé une vidéo qui explique mon besoin et surement sur le même principe que ce que tu me disais.
    Dans mon form1, j'ai donc le code suivant :
    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
     
     private void buttonPrixPromo_Click(object sender, EventArgs e)
            {
                using(objfrmShowProgress objwait = new objfrmShowProgress(CallExtractionAgil))
                {
                    objwait.ShowDialog();
                }
            }
     
            public void CallExtractionAgil()
            {
                //DECLARATION
                string SQL;
     
                // ASSIGNATION
                // Défini le répertoire d'écriture de fichier dans /mesdocuments en se basant sur l'environnement windows
                string pathExport = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                string NomFichier = "Extraction_prix_promo" + TodayDate + ".xls";
                SQL = "SELECT - from Matable; ";
     
                ExportExcelFile Exp = new ExportExcelFile();
                Exp.ExportToXls(SQL, NomFichier, pathExport);
     
            }
    Ensuite, dans mon windows form qui sert de "loading screen, j'ai le code suivant :
    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
     
     public Action Worker { get; set; }
            public objfrmShowProgress(Action Worker)
            {
                InitializeComponent();
                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
     
                if (Worker == null)
                     throw new ArgumentNullException();
                Worker = Worker;
            }
     
            private void objfrmShowProgress_Load(object sender, EventArgs e)
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            }
     
            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
                Task.Factory.StartNew(Worker).ContinueWith(t => { this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
            }
    Quand je lance le débuguer, pas d'error, la form s'affiche, tout bien, mais j'ai l'impression de ne jamais arriver dans ma procédure CallExtractionAgil. J'ai mis des points d'arrêts dans le form1 au niveau du bouton_click et au niveau de ma procédure + un point d'arrêt dans ma form d'attente.
    Le débugueur va jusqu'à la ligne "Task.factory....." Mais ensuite plus rien ne se passe, et mon fichier n'est bien entendu pas écrit... J'en déduis donc que jamais je ne rentre dans ma fonction CallExtractionAgil mais je ne sais pas pourquoi...

    Bisous bisous

  4. #4
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    260
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 260
    Points : 386
    Points
    386
    Par défaut
    Bon en fait je suis bête... Variables sensibles à la casse...

    Dans ma form de chargement, j'ai mis la variable "Worker" dans ma déclaration au lieu de "worker"... Ahlala, la sensibilité à la casse des variables, quelle tristesse...


    Du coup, merci de ton aide, parce que tu as pu m'aguiller dans mes recherches autrement que ce que j'imaginais à la base

    Bisous bisous

  5. #5
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Le *.exe est un programme externe qui n'a rien à voir.

    Voici un petit exemple rapide.

    Je crée une classe abstraite "BaseRunnable" qui implémente le nécessaire pour pouvoir exécuter un traitement et rapporter son avancement :
    Code csharp : 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
     
    namespace WaitForm
    {
        public class ProgressEventArgs
        {
            public int Spent { get; }
     
            public ProgressEventArgs(int spent)
            {
                Spent = spent;
            }
     
        }
     
        public abstract class BaseRunnable
        {
            public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);
     
            public event ProgressEventHandler ProgressEvent;
     
            public int Duration { get; }
            public int Spent { get; protected set; }
            public int Remain
            {
                get
                {
                    return Duration - Spent;
                }
            }
     
            public BaseRunnable(int duration)
            {
                Duration = duration;
            }
     
            public abstract void Run();
     
            protected virtual void ProgressEventReport()
            {
                // Raise the event in a thread-safe manner using the ?. operator.
                ProgressEvent?.Invoke(this, new ProgressEventArgs(Spent));
            }
        }
    }

    Ensuite, je crée une classe qui va effectivement faire le traitement : (ici, simplement une boucle de Sleep())
    Code csharp : 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
     
    using System.Threading;
     
    namespace WaitForm
    {
        public class Job : BaseRunnable
        {
            public Job(int duration) : base(duration) { }
     
            public override void Run()
            {
                while (Remain > 0)
                {
                    Spent++;
                    ProgressEventReport();
                    Thread.Sleep(50);
                }
            }
        }
    }

    Et tant qu'à faire, une seconde :
    Code csharp : 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
     
    using System;
    using System.Threading;
     
    namespace WaitForm
    {
        public class AutreJob : BaseRunnable
        {
            public AutreJob(int duration) : base(duration) { }
     
            public override void Run()
            {
                Random rnd = new Random();
     
                while (Remain > 0)
                {
                    Spent++;
                    ProgressEventReport();
                    Thread.Sleep(rnd.Next(10, 1000));
                }
            }
        }
    }

    Puis je fais ma form d'attente. Elle contient une progressbar histoire que ce soit plus sympa :
    Code csharp : 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
     
    using System;
    using System.Windows.Forms;
     
    namespace WaitForm
    {
        public partial class FrmWait : Form
        {
            private BaseRunnable Job;
     
            public FrmWait()
            {
                InitializeComponent();
            }
     
            public void SetJob(BaseRunnable job)
            {
                Job = job;
                progressBar1.Maximum = Job.Duration;
                Job.ProgressEvent += Job_ProgressEvent;
            }
     
            private void Job_ProgressEvent(object sender, ProgressEventArgs e)
            {
                progressBar1.Value = Job.Spent;
                Refresh();
            }
     
            private void FrmWait_Shown(object sender, EventArgs e)
            {
                Job.Run();
                Close();
            }
        }
    }

    Et dans ma form principale, je déclare simplement la form d'attente en lui filant le job à faire :
    Code csharp : 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
     
    using System;
    using System.Windows.Forms;
     
    namespace WaitForm
    {
        public partial class FrmMain : Form
        {
            public FrmMain()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Job job = new Job(100);
     
                FrmWait frmWait = new FrmWait();
                frmWait.SetJob(job);
                frmWait.ShowDialog();
            }
     
            private void button2_Click(object sender, EventArgs e)
            {
                AutreJob job = new AutreJob(20);
     
                FrmWait frmWait = new FrmWait();
                frmWait.SetJob(job);
                frmWait.ShowDialog();
            }
        }
    }

    J'espère que c'est plus clair comme ça

    -- Edit : hmpf trop lent ^^

  6. #6
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    260
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 260
    Points : 386
    Points
    386
    Par défaut
    Ahaha trop lent oui :p

    Mais les détails sont supers clairs et ca m'a aidé et ca aidera surement encore d'autres personnes dans le besoin alors merci

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/03/2015, 14h57
  2. [Débutant] Execution d'une action tant que le bouton est cliqué
    Par Martipit dans le forum VB.NET
    Réponses: 4
    Dernier message: 10/11/2012, 20h14
  3. Réponses: 2
    Dernier message: 15/03/2011, 09h49
  4. Réponses: 6
    Dernier message: 04/06/2008, 23h11
  5. Réponses: 3
    Dernier message: 30/08/2007, 12h58

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