Welcome to today’s post.
In today’s post I will discuss using the basic asynchronous programming patterns in .NET Core Applications.
First, I will look at the basic pattern for declaring an asynchronous method in C#.
To declare an asynchronous method, we need to declare the namespace:
using System.Threading.Tasks;
The basic asynchronous method is declared as follows:
public async Task AsyncMethod()
{
// do something.
..
await AnotherAsyncMethod();
}
In fact, since C# v5.0, with typical Web API controllers, the standard practice is to implement controllers with the async pattern. An example is shown below:
[HttpPost("api/[controller]/Create")]
public async Task<ActionResult> Create([FromBody]
BookViewModel model)
{
try
{
.. does something
BookViewModel book = ...
await _bookService.SaveBook(book);
return Ok(book);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return BadRequest("Cannot create book record.");
}
}
The reason for using this common asynchronous pattern is that HTTP web API requests are all asynchronous. If the call chain contains one synchronous call, then there is a likelihood of deadlocked context.
There are a few different types of asynchronous methods.
The simplest is the one without any return value. It is equivalent to a void return asynchronous method.
An example is shown below from a service class:
public async Task SaveBook(BookViewModel vm)
{
_db.Add(vm);
await _db.SaveChangesAsync();
}
For asynchronous calls to data contexts to be successful, the DbContext lifetime must be scoped within the web API request. With a transient lifetime, the transaction will fail.
To call this method, use the following pattern:
BookViewModel book = new BookViewModel()
{
// assign object properties
}
await _bookService.SaveBook(book);
The next type of asynchronous method returns an instance object.
An example is shown below from a service class:
public async Task<BookViewModel> GetBook(int id)
{
BookLoan.Models.BookViewModel book =
await _db.Books.Where(m => m.ID == id).SingleOrDefaultAsync();
if (book != null)
return book;
return null;
}
To call this method, use the following pattern:
BookViewModel bvm = new BookViewModel();
bvm = await _bookService.GetBook(id);
The next type of asynchronous method returns a list of an instance object.
An example is shown below from a service class:
public async Task<List<BookViewModel>> GetBooks()
{
return await _db.Books.ToListAsync();
}
The above will return asynchronously as the collection libraries are thread safe.
To call this method, use the following pattern:
IList<BookViewModel> book = new List<BookViewModel>();
…
book = await _bookService.GetBooks();
Note: All methods from the following static class in EF Core that return a Task object:
Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
are asynchronous methods that return a Task object or collection of Task objects.
For example:
public static Task<TSource> SingleOrDefaultAsync<TSource>(…);
Note: All methods from the following static class in EF Core that return a Task object:
Microsoft.EntityFrameworkCore.DbContext
are asynchronous methods that return a Task object or collection of Task objects.
public virtual Task<int> SaveChangesAsync(
CancellationToken cancellationToken = default(CancellationToken));
As I mentioned earlier, calls using EF Core libraries have threads scoped to the web request.
The other pattern I would like to explain is calling an asynchronous method from a synchronous method. An example of this is shown below:
public void Initialize(ApplicationDbContext context)
{
var appOptions = new AppConfiguration();
Configuration.GetSection("AppSettings").Bind(appOptions);
SeedAccounts seed_acc = new SeedAccounts(context, appOptions);
var task = Task.Run(async() => await
seed_acc.GenerateUserAccounts());
var result = task.Wait(5000);
}
What this call does is to run the asynchronous call within a thread, then stores the results of the call within a Task object. The results of the task object return to the calling method after a short delay.
There is a case where you cannot use the async … await pattern because your method is declared synchronously and there are no asynchronous calls within your method.
In this case you can use the GetAwaiter().GetResult() which, after the asynchronous call to the target method, will block the return result synchronously:
Task<bool> isInMemberRoleAction =
_userRoleService.IsUserInRole(username, "Member");
bool isInMemberRole =
isInMemberRoleAction.GetAwaiter().GetResult();
if (isInMemberRole)
{
…
}
Warning: Using GetResult() within a single-threaded context, such as a Windows application can deadlock the main UI thread.
Another context where this might be used is within an NUnit test that are run synchronously and may be calling asynchronous methods to determine test assertions.
For example:
var bookService = new BookService(context, null);
var books = bookService.GetBooks().GetAwaiter();
var result = books.GetResult();
Assert.AreEqual(3, result.Count);
That’s all for this post.
I hope you found it useful and informative.

Andrew Halil is a blogger, author and software developer with expertise of many areas in the information technology industry including full-stack web and native cloud based development, test driven development and Devops.