Async
Code

Jan 02

Introduction

Recently I came across (another) incorrect implementation of async code which has prompted me to write this post. Async methods are an encouraged code/design implementation but it is important to understand how it works and have some guidelines about using it. If you use it incorrectly, it will slow your application down rather than improving it.

The first thing to understand is that adding the async keyword does add code and overhead to the method in the compiled output. That little keyword implements and creates code that manages all the C# delegates and threads switching behind the scenes that were originally handwritten by us developers. Today it is just an abstraction of 'best practices' learned from the past.

Belive it or not you could create async code back in C# 1.1. But by C# 5 all that knowledge was perfected and the async keyword was added to the language.

I did a quick look up to refresh myself before writing this post and found this article which does a good job of talking about how it works and tips for using it.

The issue that caused me to write this post is when the async method is added to a WebApi method but there is no await keyword used in the method. In a nutshell, this renders the method as a synchronous method with the overhead of async code. Not what the user is often intending. You should always check those green squiggle lines that Visual Studio puts there.

[HttpGet]
[Route("api/mymethod")]
public async Task<IHttpActionResultMyMethod()
{
    var response = new List<String>() { "A""B" };
    return this.Ok(response);
}

Async Error

Usually, such a method will have a call off to some other method or function as opposed to my inline code sample for this post. The easiest way to fix this is to add the await keyword and wrap the call in Task.FromResult(). This will ensure the proper implementation of an async method.

[HttpGet]
[Route("api/mymethod")]
public async Task<IHttpActionResultMyMethod()
{
    var response = await Task.FromResult(new List<String>() { "A""B" });
    return this.Ok(response);
}

When to use Async?

Making every method an async method is also another bad piece of advice. The primary time to use it is when your code requires to go outside of its 'application domain'. Basically whenever you access something outside of your websites running process.

  • Any network call such as an HTTP or FTP request
  • Accessing a database
  • Accessing the file system

The second time is when your code is going to be doing something that you know will take some time. Like processing some large datasets or your wife's Christmas present list. In this case, you should use Task.Run() which creates a new thread to run the process.

There is no way my wife will read this so I'm good. :-)

Except

I mentioned you should use async when accessing a database but not when you are accessing the Sitefinity database using the Sitefinity API. Sitefinity has already implemented async methods throughout their code so it is not imperative that you wrap every 'xxxManager' call for data in an async method. If you were writing your own ADO.NET code to access the Sitefinity database then, in this case, you should implement async methods.

Expect when

Where you would wrap your Sitefinity manger calls in async methods would be when you are, as an example, calling the NewsManager and the BlogsManager and then processing the results. In this scenario, you may want to look at making both the calls async along with a Task.AwaitAll() to basically say, create two await tasks to get each data set and when both have returned act on the results.

Rounding Off

I didn't intend to go into a lot of detail about writing async code as I wanted to just point out some simple guidelines I go by and the repeated problem that I pointed out at the start.

I now also recommend you read the article linked at the start as I think it's the best summary of async usage I have read to date. It gave me a good point which made me go back and check what I was doing in some recent projects.

I will leave you with an example of an async method for calling a database via ADO.NET that you can copy if you need to do such a task.

private async Task<List<ExcursionDetail>> MyExcursions(String p1Int32 p2)
{
	List<ExcursionDetailexcursions = new List<ExcursionDetail>();
 
	try
	{
		String conn = "connString";
		using (SqlConnection connection = new SqlConnection(conn))
		{
			await connection.OpenAsync().ConfigureAwait(false);
 
			using (SqlCommand command = new SqlCommand(@"ReturnMyExcursions"connection))
			{
				command.CommandType = System.Data.CommandType.StoredProcedure;
				command.CommandTimeout = 5;
				command.Parameters.Add(new SqlParameter("@Param1"p1));
				command.Parameters.Add(new SqlParameter("@Param2"p2));
 
				using (SqlDataReader reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
				{
					if (reader.HasRows)
					{
						while (await reader.ReadAsync().ConfigureAwait(false))
						{
							//process results
						}
					}
				}
			}
		}
	}
	catch (Exception ex)
	{
		Log.Write("Error-" + ex.Message);
	}
 
	return excursions;
}

Darrin Robertson - Sitefinity Developer

Thanks for reading and feel free to comment - Darrin Robertson

If I was really helpful and you would buy me a coffee if you could, yay! You can.


Leave a comment
Load more comments

Make a Comment

recapcha code