web-dev-qa-db-fra.com

Comment afficher un contrôle de chargement pendant la fin d'un processus?

J'ai décidé d'utiliser ce composant tiers pour effectuer un contrôle de chargement simple dans mon formulaire Windows.

http://www.codeproject.com/Articles/14841/How-to-write-a-loading-circle-animation-in-NET

Cela fonctionne très bien lors de l'activation et de la désactivation de la modification de la propriété "Active" à true ou false dans une seule demande (une par fois). Le problème est lorsqu'un processus attend d'être servi, et je fais semblant d'activer le loadingControl avant que le processus ne démarre et je m'éteins lorsque je "pense" que le processus doit être terminé. Quand je le fais, le chargement de l'image est affiché comme une image statique. (Sans animation).

Je suis désolé pour cette question, je suis nouveau en C #. Mais je pense que je dois utiliser des threads ou quelque chose de similaire.

Donc, mon code général est le suivant:

using [libraries here]...;
namespace [namespace here]
{
    Public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.loadingCircle1.Visible = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(showLoading));
            this.loadingCircle1.Visible = true;
            t.Start();

            //Import an Excel

            t.Abort();
        }

        public void showLoading()
        {
            loadingCircle1.Active = true;
            loadingCircle1.RotationSpeed = 10;
        }
    }
}

Mais toujours le chargement s'affiche comme une image statique sans l'animation.

12
Edgar Alfonso

Vous créez un thread, qui définit simplement deux propriétés, puis se termine. Le t.Abort ne fera probablement rien, puisque le thread aura été quitté à ce moment-là. Pire encore, vous importez le fichier Excel sur le thread d'interface utilisateur, ce qui bloque toute animation et fige l'interface utilisateur complète.

Voici comment vous devez le faire:

Remarque: Bien sûr, si votre formulaire est réactif, vous devez désactiver/activer les contrôles et préparer au cas ce qui se passe si votre formulaire est fermé pendant la charge.

1. Utilisation de threads

Si vous voulez vraiment utiliser explicitement des threads, faites-le comme ceci:

public partial class Form1 : Form
{
    public Form1()
    {            
        InitializeComponent();
    }

    private Thread workerThread = null;

    private void btnImport_Click(object sender, EventArgs e)
    {
        // start the animation (I used a progress bar, start your circle here)
        progressBar1.Visible = true;
        progressBar1.Style = ProgressBarStyle.Marquee;

        // start the job and the timer, which polls the thread
        btnImport.Enabled = false;
        workerThread = new Thread(LoadExcel);
        workerThread.Start();
        timer1.Interval = 100;
        timer1.Start();
    }

    private void LoadExcel()
    {
        // some work takes 5 sec
        Thread.Sleep(5000);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (workerThread == null)
        {
            timer1.Stop();
            return;
        }

        // still works: exiting
        if (workerThread.IsAlive)
            return;

        // finished
        btnImport.Enabled = true;
        timer1.Stop();
        progressBar1.Visible = false;
        workerThread = null;
    }
}

2. Travailleur d'arrière-plan

BackgroundWorker peut lancer un événement lorsqu'il est terminé:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
        backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;
    }


    private void btnImport_Click(object sender, EventArgs e)
    {
        // start the animation
        progressBar1.Visible = true;
        progressBar1.Style = ProgressBarStyle.Marquee;

        // start the job
        btnImport.Enabled = false;
        backgroundWorker1.RunWorkerAsync();
    }

    private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        LoadExcel();
    }

    private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        btnImport.Enabled = true;
        progressBar1.Visible = false;
    }

    private void LoadExcel()
    {
        // some work takes 5 sec
        Thread.Sleep(5000);
    }
}

. Utilisation de async-wait

Ceci est le plus simple.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void btnImport_Click(object sender, EventArgs e)
    {
        // start the waiting animation
        progressBar1.Visible = true;
        progressBar1.Style = ProgressBarStyle.Marquee;

        // simply start and await the loading task
        btnImport.Enabled = false;
        await Task.Run(() => LoadExcel());

        // re-enable things
        btnImport.Enabled = true;
        progressBar1.Visible = false;
    }

    private void LoadExcel()
    {
        // some work takes 5 sec
        Thread.Sleep(5000);
    }
}
28
György Kőszeg

Je recommanderais d'utiliser async/wait (pour C # 5.0):

private void button1_Click(object sender, EventArgs e){
    ImportAsync();
}

private async Task ImportAsync(){
    // UI-thread
    showLoading();
    this.loadingCircle1.Visible = true;

    // wait until task will be finished
    await Task.Run(() => {
        // different non-blocking thread for all the hard work, but without UI-stuff
        // import an Excel
    });

    // going back to UI-thread
    this.loadingCircle1.Visible = false;
}
7
Surfin Bird