4

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;
 }
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
DartAlex
  • 264
  • 1
  • 2
  • 9
  • Why the mix of threads and tasks? Choose one, not both. Choose TPL, IMHO. – Maarten Aug 25 '16 at 08:44
  • Take a look at [Load data asynchronously into my DataTable in Windows Forms](http://stackoverflow.com/a/38427392/3110834). – Reza Aghaei Aug 25 '16 at 08:59
  • Also if you may be interested in [Showing Transparent Loading Spinner above other Controls](http://stackoverflow.com/a/37473192/3110834) – Reza Aghaei Aug 25 '16 at 09:01
  • Reza Aghaei, [this](http://stackoverflow.com/questions/37220327/show-transparent-loading-spinner-above-other-controls/37473192#37473192) is what I need, thank you! – DartAlex Aug 25 '16 at 09:07
  • @DartAlex If you use the loading spinner without making your load data asynchronous, probably you will see the spinner doesn't spin or is frozen. So you need to make your load data asynchronous. – Reza Aghaei Aug 25 '16 at 09:12
  • @Reza-Aghaei I'll try, but do not want to lose speed in loading data. Thanks for the advice. – DartAlex Aug 25 '16 at 09:30
  • @DartAlex It's just and example to create delay. You need to use asynchronos way to load data. Show the loading before `LoadData` and hid it after `LoadData`. Read my previous comments. – Reza Aghaei Aug 25 '16 at 09:31
  • Take a look at the answer which clarifies what I said in comments. – Reza Aghaei Aug 25 '16 at 10:16
  • The most important thing that you should consider, is *When the form is frozen, it means the UI thread is too busy and so even of you try to show a loading animation, it will not animate. You should load data asynchronously.* – Reza Aghaei Aug 25 '16 at 10:55

1 Answers1

10

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 then 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 transparent loading image.

enter image description here

public async Task<DataTable> GetDataAsync(string command, string connection)
{
    var dt = new DataTable();
    using (var da = new SqlDataAdapter(command, connection))
        await Task.Run(() => { da.Fill(dt); });
    return dt;
}

private async void LoadDataButton_Click(object sender, EventArgs e)
{
    loadingPictureBox.Show();
    loadingPictureBox.Update();
    try
    {
        var command = @"SELECT * FROM Category";
        var connection = @"Your Connection String";
        var data = await GetDataAsync(command, connection);
        dataGridView1.DataSource = data;
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
    loadingPictureBox.Hide();
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • I found that in my example and in your, animation freezes on `dataGridView1.DataSource = data;` I can `await` SQL-queries, but as soon as there is a reference to the form, it animation is froze. Maybe create a new transparent form and show animation on her? – DartAlex Aug 25 '16 at 11:33
  • That display of data takes time – DartAlex Aug 25 '16 at 11:36
  • 2
    I used 100,000 records and the delay was 250-400 milliseconds. If you want to load more records, it's better to rethink about the way you want to show data. You need to use a paging mechanism or using data grid view in virtual mode and show data page by page. – Reza Aghaei Aug 25 '16 at 11:47
  • 1
    For example, I showed 100 records of 100,000 records which I loaded in each page and data-binding took about 10 milliseconds to show data of each page. – Reza Aghaei Aug 25 '16 at 11:55
  • I load 10 DataGridView and during each display data - animation delay. In the case of one large table, your example is ideal. – DartAlex Aug 25 '16 at 11:57
  • 1
    I believe for the current post, it's useful answer. Since the problem now is the delay when performing data-binding and not delay when loading data, I recommend you to ask a new question inspired by this answer. – Reza Aghaei Aug 25 '16 at 12:01
  • I can guess the answer for that question would be something like *Since you should perform data-binding in UI thread, if the data-binding itself is time-consuming you should use a mechanism like paging.* – Reza Aghaei Aug 25 '16 at 12:04