How can I display a loading control while a process is waiting for be finished?

You create a thread, which simply sets two properties and then ends. The t.Abort will probably do nothing, since the thread will have been exited by that time. Even worse, you import the excel file on the UI thread, which blocks any animation and freezes the complete UI.

This is how you should make it:

Remark: Of course if your form is responsive, you must disable/enable the controls and prepare to the case what happens if your form is being closed during the load.

1. Using threads

If you really want to explicitly use threads, do it like this:

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. Background worker

The BackgroundWorker can throw an event when it is finished:

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);
    }
}

3. Using async-await

This is the simplest one.

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);
    }
}

Leave a Comment