1

i have a datagridview and it take times to load it datasource . i want to make a loading for it and i tried background workers and async await and task.factory.startnew and task.run and ... but when datagridview is filling my loading gif will be freezed.

what should i do?

i googled a lot and i saw a text. they said we have just one ui thread and when one is working another will be freezed is that correct? i have seen many post like this situation and i have tried them for 5 days but unsuccessful. maybe there is a clear thing that i cant see.

for example, it is like a situation that gif is loading and a richtextbox is filling: pictureBox1 will be freezed when we are in huge function

private  void  button1_Click (object sender, EventArgs e)
   {

     Task.Factory.StartNew(()=>;
     {
         huge();
     }
         );

   }



private void huge()
    {
        richTextBox1.Invoke(new EventHandler(delegate
            {


                    for (int i = 0; i < 10000; i++)
                    {
                        richTextBox1.Text += "s";
                    }

            }));
        pictureBox1.Visible = false;
    }
Farshad
  • 325
  • 2
  • 15
  • Using a backgroundworker should solve the locking issue. Make sure you code to load is really in the backgroundworker. – jdweng Nov 06 '16 at 13:21
  • In your method you are performing the task in UI thread using `Invoke` so the UI thread keeps busy.You can use an async/await pattern. You may find [this post](http://stackoverflow.com/a/39142535/3110834) useful. – Reza Aghaei Nov 06 '16 at 13:34
  • i add this in click BackgroundWorker bg = new BackgroundWorker(); bg.DoWork += bg_DoWork; bg.RunWorkerAsync(); and same happened agian.@jdweng – Farshad Nov 06 '16 at 13:39
  • i used this in click method: uiPBLoading.Visible = true; var data = await GetDataAsync(); DGV_ListEditCustomer.DataSource = data; uiPBLoading.Visible = false; and as you said, i wrote it: public async Task GetDataAsync() { List LCT = new List { }; LCT = CustomerBR.GetCustomerList(); DataTable table=null; await Task.Factory.StartNew(() => { table = UtilHandler.ToDataTable(LCT); }); return table; } again freezed!@RezaAghaei – Farshad Nov 06 '16 at 14:00
  • i have about 4000 records – Farshad Nov 06 '16 at 14:27
  • @Farshad The example is really simple to follow. It's not complicated at all. Also [here](http://stackoverflow.com/revisions/38427392/3) is an implementation which uses EF and List. – Reza Aghaei Nov 06 '16 at 15:23
  • Use [VirtualMode](https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.virtualmode(v=vs.110).aspx). See [here](https://msdn.microsoft.com/en-us/library/ms171621(v=vs.110).aspx). – Alexander Petrov Nov 06 '16 at 19:16
  • This line of code is where your UI thread get busy: `CustomerBR.GetCustomerList();` In fact the main point which should be run async is this line. See [this link](http://stackoverflow.com/revisions/38427392/3). Also you should know you don't need to convert a `List` to a `DataTable` to be able to show it in a list, it's enough to set `List` as data source of your data grid view. – Reza Aghaei Nov 07 '16 at 18:59

1 Answers1

0

Let me explain what you do here:

 Task.Factory.StartNew(()=>;
     {
         huge();
     }
         );

=> Create a thread to excecute the huge function

 richTextBox1.Invoke(new EventHandler(delegate
            {


                    for (int i = 0; i < 10000; i++)
                    {
                        richTextBox1.Text += "s";
                    }

            }));

=> Invoke the UI thread (and as you said: we have only one UI Thread which executes synchronously) and run a loop to update a textBox.

Thus, I don't know what you tried to do, but usually what we do is that we run some dataLoading/Fetching function in a backgroundworker for example, and here, after every X percent of loading we invoke the UI Thread to update information for the user.

It seems that in your case you only display a gif as a waiter for the user. Thus you should be able to do something like:

private  void  button1_Click (object sender, EventArgs e)
   {
     DisplayMyGif(); //will display the gif on the UI thread, because click always comes from the UI
     Task.Factory.StartNew(()=>;
     {
         LoadMyData(); //should load the data asynchronously on a different Thread
     }
         );

   }

Hope it helps.

Community
  • 1
  • 1
Ouarzy
  • 3,015
  • 1
  • 16
  • 19
  • would you please give me your email address?i just want to send my code lines and it is just about 3 functions but it is 400 letter long for commenting here – Farshad Nov 06 '16 at 14:57