Making A Simple Non-Freezing Window Forms Application

This example can be used in Get records from DB, or to call a long running task and more.

Create our Windows Form

Create a Simple Windows Forms Application in Visual Studio.

Window Forms

click event at button

Now put a click event at button, and write the following code,

  1. private void button1_Click(object sender, EventArgs e)  
  2. {  
  3.     for (var i = 0; i <= 1000000; i++)  
  4.     {  
  5.         label1.Text = @"Count : " + i;  
  6.     }  
  7. }  
Run the application and click Start… You will see our application Freezes. Look at Task Manager to see Not Responding status.

Freezes

How can we get around this

Let’s put another button in our form and add a click event.

Form

At click event method, write the following code,
  1. //attributes used to refresh UI  
  2. private readonly SynchronizationContext synchronizationContext;  
  3. private DateTime previousTime = DateTime.Now;  
  4.   
  5. public Form1()  
  6. {  
  7.     InitializeComponent();  
  8.     synchronizationContext = SynchronizationContext.Current; //context from UI thread  
  9. }  
  10.   
  11.   
  12. private async void button2_Click(object sender, EventArgs e)  
  13. {  
  14.     button1.Enabled = false;  
  15.     button2.Enabled = false;  
  16.     var count = 0;  
  17.   
  18.     await Task.Run(() =>  
  19.     {  
  20.         for (var i = 0; i <= 1000000; i++)  
  21.         {  
  22.             UpdateUI(i);  
  23.             count = i;  
  24.         }  
  25.     });  
  26.     label1.Text = @"Count : " + count;  
  27.     button1.Enabled = true;  
  28.     button1.Enabled = false;  
  29. }  
  30.   
  31. public void UpdateUI(int value)  
  32. {  
  33.     var timeNow = DateTime.Now;  
  34.   
  35.     //Here we only refresh our UI each 50 ms  
  36.     if ((DateTime.Now - previousTime).Milliseconds <= 50) return;  
  37.   
  38.     //Send the update to our UI thread  
  39.     synchronizationContext.Post(new SendOrPostCallback(o =>  
  40.     {  
  41.         label1.Text = @"Count : " + (int)o;  
  42.     }), value);  
  43.   
  44.     previousTime = timeNow;  
  45. }  

I placed the word ASYNC at click event method to avoid our UI to freeze. At our event look to TASK that make our count. Inside it you will see the method UpdateUI, that refresh the label 50ms each.

Run the application and see the result.
 
Conclusion

I hope with this tutorial you learned a little about how we can avoid Freezes at our Desktop Applications. You can use the target idea from this tutorial to improve scenarios like Db Queries, a long running task, read an external file and much more.