English
Français

Blog of Denis VOITURON

for a better .NET world

Asynchronous Simplified

Posted on 2014-07-17

Introduction

For recent developments, users want reactive graphical interfaces, even if you need to recover data from external sources (ex. with web services). The best solution is to create asynchronous operations to let a responsive UI. Since the Framework 4.5, Microsoft offers a new and easy way to use asynchronous methods.

Basically, you can create a software with two methods:

public void LongMethod()
{
    System.Threading.Thread.Sleep(2000);
}
public string QuickMethod()
{
    System.Threading.Thread.Sleep(1000);
    return "ABC";
}

1. Synchronous methods

when you start successively these two methods, of course the User Interface freezes until the procedure is completed.

MyLongMethod();
MyQuickMethod();

And the execution traces will be… and my UI not responding.

2. Classic Asynchronous methods

To avoid the UI freezes, you can run these methods into two Threads, via Task.Factory.StartNew or simply Task.Run (see difference on PFXTeaml’s Blog).

Task.Run( () => MyLongMethod() );
Task.Run( () => MyQuickMethod() );

And the execution traces will be… My UI is responding, but of course, you can see a problem: the Main Finished come before each method Finished steps.

3. async / await methods

The best solution, is to use the new async / await keywords. In this case, my methods will be run in different threads (versus my UI) and they wait each finish to continue my main program. And note that, by convention, a method called asynchronously will be suffixed by the Async keyword.

async void Go()
{
   await MyLongMethodAsync();
   await MyQuickMethodAsync();
}

</p><p style="margin-left:36pt;">And the execution traces will be… My UI is responding, and the program workflow is correct. </p><p> </p><h2>Quick Tips </h2><p>Unfortunately, if you try to update a UI component or a Collection binded to your UI, from a thread, you’ll receive a NotSupportedException. </p><p>You can solve that with two different methods (for a WPF application): </p><ul><li>The full parameterized method, where you can define a priority level and a timeout beyond which the process will be canceled. </li></ul><p>

Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
                                      TimeSpan.FromSeconds(1),
                                      new Action( () =>
   {
      // Method to execute in the UI Thread.
      this.ConsoleItems.Add(new ConsoleItem(text, level));
   }
));

</p><ul><li>The light method: before run your asynchronous methods, keep a reference of UI (SynchronizationContext.Current), and next call the Send method. </li></ul><p>

public SynchronizationContext UIContext { get; set; }

UIContext.Send((state) =>
{
   // Method to execute in the UI Thread.
   this.ConsoleItems.Add(new ConsoleItem(text, level));
},
null);

</p><p>  </p><p>Finally, if sometime you need to run some methods in a Thread different of UI Thread, but you must ensure that all of these methods will be run in the same Thread (only one). So, download the StaTaskScheduler class wrote by Microsoft and available in a ParallelExtensionsExtras package and write your async method like that: </p><p>

StaTaskScheduler _sta = new StaTaskScheduler(1); // 1 is the NumberOfThreads

Task<TResult> RunTask<TResult>(Func<TResult> function)
{
   return Task.Factory.StartNew<TResult>(function, CancellationToken.None, TaskCreationOptions.None, _sta);
}

</p>

Languages

EnglishEnglish
FrenchFrançais

Follow me

Recent posts