Asynchronous tasks on Winform

Posted on : 11-05-2009 | By : manitra | In : C#, Developpement, WinForm

2

The problem

When you create winform applications, doing tasks in the background is essential to avoid user frustation. Unfortunatly, it could make you write a lot more code. Here are some utility methods that reduce the complexity of asynchronous calls within windows forms.

Within you base class

You probably have a common base class for all your UI components. Add these methods :

  1. namespace TestWinForm
  2. {
  3.     public class BaseForm : Form
  4.     {
  5.         // Execute some code in async mode.
  6.         // When it's done, it calls the nextStep delegate, eventually with
  7.         // an exception catched during the main action.
  8.         protected virtual void Async(Action action, Action nextStep)
  9.         {
  10.             new Thread(delegate()
  11.             {
  12.                 Exception exception = null;
  13.                 try
  14.                 {
  15.                     action();
  16.                 }
  17.                 catch (Exception ex)
  18.                 {
  19.                     exception = ex;
  20.                 }
  21.                 ThreadSafe(() => { nextStep(exception ); });
  22.             }).Start();
  23.         }
  24.  
  25.         // This allows a sub class to easily run a method within
  26.         // an UI thread without the need of creating multiple
  27.         // delegate signatures for each method signatures
  28.         protected virtual void ThreadSafe(MethodInvoker method)
  29.         {
  30.             if (InvokeRequired)
  31.                 Invoke(method);
  32.             else
  33.                 method();
  34.         }
  35.     }
  36. }

Within your UI classes

Now the only thing you need to do is to encapsulate the methode content with the Async() method :

namespace TestWinForm
  1. {
  2.     public partial class MainForm : BaseForm
  3.     {
  4.         public MainForm()
  5.         {
  6.             InitializeComponent();
  7.         }
  8.  
  9.         // Here is the async trick :
  10.         // – UI will NOT freeze,
  11.         // – you can add beautifull animated gifs
  12.         private void button1_Click(object sender, EventArgs e)
  13.         {
  14.             DateTime? result = null;
  15.             Async(
  16.                 () =>
  17.                 {
  18.                     result = GetComplexDate();
  19.                 },
  20.                 (ex) =>
  21.                 {
  22.                     if (ex == null)
  23.                         textBox1.Text = result.Value.ToShortDateString();
  24.                     else
  25.                         textBox1.Text = ex.Message;
  26.                 }
  27.             );
  28.         }
  29.  
  30.         // This is the slow, data-intensive task :p
  31.         private DateTime? GetComplexDate()
  32.         {
  33.             Thread.Sleep(3000);
  34.             return DateTime.Now;
  35.         }
  36.     }
  37. }

The traditional way

Just in case you didn’t get it. This is what you should NOT DO:

// This was traditional way :
  1.         // – UI will freeze until during 3 second …
  2.         // – you users will complain
  3.         // avoid this !
  4.         private void button1_Click2(object sender, EventArgs e)
  5.         {
  6.             try
  7.             {
  8.                 textBox1.Text = GetComplexDate().ToShortDateString();
  9.             }
  10.             catch (Exception ex)
  11.             {
  12.                 textBox1.Text = ex.Message;
  13.             }
  14.         }

Happy coding !