Using async / await

2012/01/15

Using async / await

this post will discuss parallel disposal.

async, await, parallel, task,tpl, using

whenever we want to dispose a parallel execution upon completion we can’t use the convenient using keyword.

for example, the following code may be dispose the command before completion:

Very bad Code Snippet
  1. using (var conn = new SqlConnection(CONN_STR))
  2. using (var cmd = new SqlCommand("Select * from Employee", conn))
  3. {
  4.     conn.Open();
  5.     cmd.BeginExecuteReader(ar =>
  6.         {
  7.             int affected = cmd.EndExecuteNonQuery(ar);
  8.         });
  9. }

the using is absolutely wrong for the above sample.

what should be done is:

Code Snippet
  1. var conn = new SqlConnection(CONN_STR);
  2. var cmd = new SqlCommand("Select * from Employee", conn);
  3. conn.Open();
  4. cmd.BeginExecuteReader(ar =>
  5. {
  6.     int affected = cmd.EndExecuteNonQuery(ar);
  7.     cmd.Dispose();
  8.     conn.Dispose();
  9. }, null);

we can write it slightly friendlier by using the TPL FromAsync wrapper:

Code Snippet
  1. var conn = new SqlConnection(CONN_STR);
  2. var cmd = new SqlCommand("Select * from Employee", conn);
  3. conn.Open();
  4. Task<int> t = Task.Factory.FromAsync<int>(
  5.     cmd.BeginExecuteReader,
  6.     cmd.EndExecuteNonQuery,
  7.     null);
  8. t.ContinueWith(tsk =>
  9.     {
  10.         int affected = tsk.Result;
  11.         cmd.Dispose();
  12.         conn.Dispose();
  13.     });

but what if the compiler can rewrite our code?

in that case we can write a similar code to the code in the first code snippet and get it compiled into something like the above code snippet above.

this is exactly what happens when in .NET 4.5 / C#5 (async / await pattern).

when we write the following code:

Code Snippet
  1. async Task<int> ExecuteNonQueryAsync()
  2. {
  3.     int affected = 0;
  4.     using (var conn = new SqlConnection(CONN_STR))
  5.     using (var cmd = new SqlCommand("Select * from Employee", conn))
  6.     {
  7.         conn.Open();
  8.         affected = await Task.Factory.FromAsync<int>(
  9.             cmd.BeginExecuteReader,
  10.             cmd.EndExecuteNonQuery,
  11.             null);
  12.     }
  13.     return affected;  
  14. }

the compiler does rewrite this async method.

everything that follow the await keyword (line 8),

will be put into a continuation state machine, including the closing of the curly brackets (of the using).

Summary

using the new async / await pattern will dispose our resources on time.

using keyword is a very clean syntax and now we can apply it to parallel execution.

Shout it

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>