Click here to Skip to main content
Click here to Skip to main content

Simplifying async calls

, 1 Feb 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
How to reduce overhead and complexity of calling async methods.

Introduction

I often find myself revisiting old code to see how a actually implemented the asynchronous calls.
More than once I thought that the async "stuff" could be wrapped so I shouldn't have to remember how to implement it. 

This article is about wrapping the async call into something more easily remembered.  

Typical async use 

This example show how I typically would implement an async call.

  public void Backup()
  {
    backupInProgress = true;
    Task<String> backup = BackupAsync();
    backup.GetAwaiter().OnCompleted(
      () =>
      {
        BackupStatus = backup.Result;
        backupInProgress = false;
      });
  }  

Where BackupAsync handles the async and await:

  private async Task<String> BackupAsync()
  {
    Func<string> a = () =>
      {
        // Do stuff here
      };
    return await Task.Run(a);
  } 

I normally use the Result from the Function/Task to update logic or UI when the asynchronous method completes.  In the example above a property BackupStatus is set. 

Reducing the code   

The async call can be wrapped into the following method: 
  public static void Do(Func<T> func, Action<T> completed)
  {
    Task<T> task = AsyncTask(func);
    task.GetAwaiter().OnCompleted(() =>
                                  {
                                    if (!task.IsFaulted) // Check if Faulted
                                      completed(task.Result);
                                  });
  } 

Where AsyncTask is defined as below:

  private static async Task<T> AsyncTask(Func<T> func)
  {
    return await Task.Run(func);
  } 

Now I can call a Function (func) asynchronously and give the result to an Action (completed) using the following code:

  Async<string>.Do(Backup, UpdateUI); 

Where Backup and UpdateUI is regular methods called asynchronously: 

  private string Backup()
  {
    // Do backup
    return "Done"; // return status
  } 

  private void UpdateUI(string status)
  {
    BackupStatus = status;
  } 

Perfect! No more async await, but how do we handle exceptions?
Well we could create an overload that call another method if the Task has IsFaulted set:

  public static void Do(Func<T> func, Action<T> completed, Action<Exception> failure)
  {
    Task<T> task = AsyncTask(func);
    task.GetAwaiter().OnCompleted(() =>
      {
        if (task.IsFaulted)
          failure(task.Exception);
        else
          completed.Invoke(task.Result);
      });
  } 
This way we can call the Do method like this:
  Async<string>.Do(Backup, UpdateUI, HandleException);  

Where HandleException: 

  private void HandleException(Exception parameter)
  {
     // Handle exception
  }  


Please look at the provided sample for additional information. 

History 

My initial thoughts.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Niel M.Thomas
Software Developer (Senior)
Denmark Denmark
Name: Niel Morgan Thomas
Born: 1970 in Denmark
Education:
Dataengineer from Odense Technical University.
More than 20 years in IT-business.
Current employment:
Working with application development in a major Danish company that produce medical equipment.

Comments and Discussions

 
BugMispelled Do function declaration Pinmemberer.blacky3-Feb-14 10:22 
GeneralRe: Mispelled Do function declaration PinmemberNiel M.Thomas3-Feb-14 19:27 
GeneralMy vote of 4 PinmemberPranay Rana2-Feb-14 23:46 
GeneralMy vote of 2 PinprofessionalPaulo Zemek2-Feb-14 4:54 
GeneralRe: My vote of 2 PinmemberWilliam E. Kempf3-Feb-14 4:18 
GeneralRe: My vote of 2 PinprofessionalPaulo Zemek3-Feb-14 4:24 
GeneralRe: My vote of 2 PinmemberWilliam E. Kempf3-Feb-14 4:38 
GeneralRe: My vote of 2 PinmemberNiel M.Thomas3-Feb-14 5:47 
GeneralRe: My vote of 2 PinmemberWilliam E. Kempf3-Feb-14 6:22 
GeneralRe: My vote of 2 PinmvpSacha Barber3-Feb-14 19:57 
QuestionI don't understand what you are trying to accomplish here. PinprofessionalPaulo Zemek2-Feb-14 4:53 
AnswerThis is the point - PinmemberNiel M.Thomas2-Feb-14 6:53 
GeneralRe: This is the point - PinprofessionalPaulo Zemek2-Feb-14 7:21 
GeneralRe: This is the point - PinmemberNiel M.Thomas2-Feb-14 9:50 
GeneralRe: This is the point - PinprofessionalPaulo Zemek2-Feb-14 10:10 
GeneralRe: This is the point - PinmvpSacha Barber2-Feb-14 22:07 
GeneralRe: This is the point - PinmemberNiel M.Thomas2-Feb-14 23:02 
AnswerRe: I don't understand what you are trying to accomplish here. PinmvpSacha Barber2-Feb-14 19:12 
GeneralRe: I don't understand what you are trying to accomplish here. PinprofessionalPaulo Zemek3-Feb-14 1:58 
QuestionI would say I see typical usage more like this PinmvpSacha Barber2-Feb-14 0:35 
AnswerRe: I would say I see typical usage more like this [modified] PinmemberNiel M.Thomas2-Feb-14 2:23 
GeneralRe: I would say I see typical usage more like this [modified] PinmvpSacha Barber2-Feb-14 19:08 
GeneralRe: I would say I see typical usage more like this PinmemberWilliam E. Kempf3-Feb-14 4:30 
GeneralRe: I would say I see typical usage more like this [modified] PinmvpSacha Barber3-Feb-14 19:52 
GeneralRe: I would say I see typical usage more like this PinmemberWilliam E. Kempf4-Feb-14 3:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.141022.2 | Last Updated 2 Feb 2014
Article Copyright 2014 by Niel M.Thomas
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid