DartAlex DartAlex - 28 days ago 7
C# Question

Show Loading animation during loading data in other thread

I have an application running with the database. When I load a tables in the datagridview, my form freezes. How to ensure the smooth load animation during loading tables?

I run two threads for animation and load data into the tables, but the animation still does not always work.

private volatile bool threadRun;

private void UpdateTab()
{
// Create panel for animation
Panel loadingPanel = new Panel();
// Label, where the text will change
Label loadingLabel = new Label();
loadingLabel.Text = "Loading";

loadingPanel.Controls.Add(loadingLabel);
this.Controls.Add(loadingPanel);

// thread loading animation
threadRun = true;

Task.Factory.StartNew(() =>
{
int i = 0;
string labelText;
while (threadRun)
{
Thread.Sleep(500);
switch (i)
{
case 0:
labelText = "Loading.";
i = 1;
break;
case 1:
labelText = "Loading..";
i = 2;
break;
default:
labelText = "Loading...";
i = 0;
break;
}
loadingLabel.BeginInvoke(new Action(() => loadingLabel.Text = labelText));
}
});

// thread update DataGridView
Thread update = new Thread(ThreadUpdateTab);
update.Start();
}

private void ThreadUpdateTab()
{
// SQL Query...
myDataGridView1.Invoke(new Action(() => myDataGridView1.DataSource = myDataSet1.Tables[0]));
// ...
myDataGridView10.Invoke(new Action(() => myDataGridView10.DataSource = myDataSet10.Tables[0]));

threadRun = false;
}

Answer Source

When the form is frozen, it means the UI thread is too busy and so even if you try to show a loading animation, it will not animate. You should load data asynchronously.

You can have an async method which returns Task<DataTable> like the GetDataAsync method which you can see in this post. Then call it in an async event handler. In the event handler, first show the loading image, then load data asynchronously and at last hide the loading image.

You can simply use a normal PictureBox showing a gif animation as loading control. Also you may want to take a look at this post to show a trasparent loading image.

enter image description here

public async Task<DataTable> GetDataAsync()
{
    var dt = new DataTable();
    var cn = @"Your Connection String";
    var cmd = @"SELECT * FROM Category";
    var da = new SqlDataAdapter(cmd, cn);
    await Task.Run(() => { da.Fill(dt); });
    return dt;
}

private async void LoadDataButton_Click(object sender, EventArgs e)
{
    loadingPictureBox.Show();
    loadingPictureBox.Update();
    try
    {
        var data = await GetDataAsync();
        dataGridView1.DataSource = data;
    }
    catch (Exception ex)
    {
        //Handle Exception
    }
    loadingPictureBox.hide();
}