.NET Asynchronous Disposal – Tips for Implementing IAsyncDisposable on your own Types

Background – Why Async Dispose?

The .NET Team recently added support for asynchronous disposal of objects, via a new IAsyncDisposable interface.

A lot of the examples you can find will use this to let you dispose of asynchronous streams, but it’s also useful for disposal of other objects that may potentially trigger I/O.

This allows you to write code like this (which works in .NET Core 3.0, with C# 8):

Notice the await in front of the using statement? That will tell the using block to call DisposeAsync on the SqlConnection object when we exit the using block, instead of the regular Dispose method, and await on the result.

What’s the benefit of this over a typical using? Well, if the database connection needs to go over the network to reset the connection, it will return the thread to the thread pool to do other work, rather than blocking it while the Dispose takes place.

The great thing about .NET Core 3.0 is that for any services you have registered as Scoped (i.e. they only live for the duration of the current HTTP request) that implement IAsyncDisposable will be disposed of asynchronously at the end of the request, giving valuable thread time back to processing actual requests.

I recently added the functionality in the Autofac Dependency Injection library to support calling DisposeAsync on a lifetime scope, which in turn calls DisposeAsync on all services in that scope that implement IAsyncDisposable. This extends to if you use Autofac as your .NET Core Service Provider as well. The functionality will be released in Autofac 5.0.0, or you can check out the relevant GitHub PR now to see what changes went in.

I thought I’d use this blog post to help people write their own classes that implement IAsyncDisposable, since I couldn’t find a lot of documentation on it, and had to go digging into .NET Core code on GitHub to figure out the best approach.

Implement IDisposable As Well

IAsyncDisposable isn’t a replacement for IDisposable, it’s an additional way to dispose.

Basically, if you implement IAsyncDisposable in your class, you should probably implement IDisposable too and perform the synchronous equivalent of your disposal operation.

This goes double for library authors, who are not in control of the code that creates the object that needs to be disposed.

There’s a couple of reasons for this:

  1. If you don’t have a regular Dispose method, code that doesn’t run in an async context will have to block on your DisposeAsync to make it sync, which kind of defies the point, and is unpleasant:
  1. If your class gets put in a container, and then the container is disposed synchronously, an exception will be thrown (this is the behaviour of Autofac and the default .NET Core DI system), because these containers will refuse to call DisposeAsync from inside a regular Dispose:
The exception we get if we don’t dispose asynchronously.

Only Add IAsyncDisposable If You Need To

This one is pretty simple; you should only add IAsyncDisposable to your class if you or a derived class may allocate resources that also implement IAsyncDisposable.

Don’t do this:

SemaphoreSlim doesn’t implement IAsyncDisposable, so all this does is use up another thread pool thread to run the Dispose.

Derived Classes

If you are writing a base class that might have derived classes with resources that need disposing asynchronously, you may wish to introduce a virtual DisposeAsync method if you also have a base Dispose method.

In this case, I would suggest making your default implementation call Dispose directly without awaiting and return synchronously:

Base classes can override the DisposeAsync method if they have resources that can be disposed of asynchronously, otherwise they can just override Dispose.

Only Dispose Once (Sync or Async)

It’s recommended practice to make Dispose re-entrant, and only dispose of its resources once. With the asynchronous disposal behaviour, this is still true, and importantly, you should only allow either Dispose or DisposeAsync to actually do the dispose.

So your classes should have this pattern:

The reason I set isDisposed to true in the above example before awaiting is because setting it afterwards would make it possible for a caller to double-dispose, by not awaiting on DisposeAsync, then calling Dispose. It’s unlikely, but possible.

If the class may be used in a multi-threaded context, consider using Interlocked methods to set isDisposed, to make sure two threads don’t try disposing at the same time.

Targeting netstandard2.0

This bit is mostly targeted at library developers, who might be targeting netstandard versions.

While the language implementations for asynchronous disposal are only available in netstandard2.1, there is a package from Microsoft that provides the IAsyncDisposable interface and related types for netstandard2.0 and .NET 4.6.1, Microsoft.Bcl.AsyncInterfaces (as David Fowler kindly pointed out to me in the Autofac PR).

This allows you to add conditional references that mean your library can implement asynchronous disposal in versions prior to .NET Standard 2.1, by adding the following conditional package reference:

Consider Adding GC.SuppressFinalize to DisposeAsync

If your class has a finalizer (or a derived class may have one), then you may already be calling GC.SuppressFinalize(this) in your Dispose method.

Because your DisposeAsync method is another Dispose method, it should also call GC.SuppressFinalize so the GC doesn’t have to call your destructor later.

This is a more complete example that provides protected virtual methods for disposal, in line with the recommended IDisposable pattern:

Putting GC.SuppressFinalize in the DisposeAsync method will actually cause a violation of the CA1816 analyzer rule if you have the analyzers installed, that says GC.SuppressFinalize should only be called from Dispose. I’m hoping that the rule will get updated at some point, but for now you may need to suppress that rule for the DisposeAsync method.


So, IAsyncDisposable can be really handy if you have resources to dispose of that may use I/O in that disposal, but be careful using it, and only add it if you actually need to!

ASP.NET Core 3.0 – Logging in the Startup Class (with NLog)

With ASP.NET Core 3.0, the ability to inject an ILogger or ILoggerFactory into the Startup class has been removed, so we can no longer do this:

I understand why this has been done, because creating a temporary DI container just for the startup process adds a lot of complexity and potential for errors.

However, my ConfigureServices method (and the new ConfigureContainer method added in 3.0) does quite a bit of work, including loading extension assemblies; I want to be able to log during that time.

I also want to make sure I only pass around the ILogger from the Microsoft.Extensions.Logging namespace to other objects used at startup.

The Workaround

I use NLog for my logging (https://nlog-project.org/). In my Program’s Main method I configure it like so:

You can grab details on how to create an nlog.config file from the NLog docs, I won’t go into it here.

Then, in my Startup class, I can create the NLogLoggerProvider class (this is sort of a factory for creating the Microsoft ILogger instances), and from that I can get my logger instance:

Hey presto, logging in the Startup class. Note that we are obviously outside the entire DI system for this logging (which is sort of the point).

Modding my Rowing Machine with an Arduino – Part 1 – Arduino Basics

I’ve got a rowing machine in my garage that I use pretty regularly, and it displays some statistics on a basic little read-out, including speed, calories burnt, number of ‘strokes’ and so on.

The rowing machine read-out.

My mission is to replace the simple LED read-out with my own board that will capture the sensor data it uses, upload it somewhere and then do some fun stuff with that data.

For background, I have a little past experience in embedded programming, but I haven’t used it in years. I understand the basics of GPIO pins and similar, but I place myself firmly in the ‘beginner’ category with embedded development.

I hadn’t touched an Arduino before today, when I started writing this post, so this is going to cover just getting to grips with Arduino basics, and subsequent updates will go through all the steps needed to mod my rowing machine!

Picking an Arduino Board

My only real criteria for picking an Arduino board is that I can connect the sensors on my rowing machine, and also that I can connect to WiFi to get data off it.

The back of the rowing machine display.

From the connections on my rowing machine, I can tell I need two connections on the board that can read analog sensor values, so I knew I would need two ADCs (Analog to Digital Converters) on my board, one for the speed and one for the counter.

Going through the Arduino website to figure out which board I wanted (turns out there’s a lot of choice), I picked the Arduino Uno Wifi Rev2, which:

  • Has 2 ADCs (for reading the sensors on my rowing machine).
  • A built-in WiFi module for connectivity (so I can upload my data).
  • A pretty attractive price of about £35 (as of writing in May 2019) plus shipping.

Shipping only took a couple of days, and once it arrived I was ready to go. You will also need a USB Type B cable. You can pick one up off Amazon for about £5, but I had an old one lying around.


After plugging in the Arduino board with the USB connector, I went to the getting started guide for my particular board (the site has different pages for each one).

I believe that a lot of the following content should work for most Arduino boards that don’t have WiFi, but I am not certain.

From there I tried out both the web-based and desktop IDE Arduino provide, but I decided I want to work in a familiar environment. Luckily, it turns out that trusty VS Code can come to my rescue, because it has an extension for working with Arduino, with the added bonus of having decent intellisense.

You will need to download the regular Arduino desktop IDE from here before you can use VS Code with your Arduino; the extension needs to use the tools it supplies.

Go ahead and install the VS Code Arduino extension (by Microsoft), then go and configure the extension if you need to set the installation path for your Arduino installation to the non-default setting.

What is an Arduino Program?

What actually is an Arduino Program anyway, and how is it different from a console application on my desktop?

Basically, all Arduino ‘programs’ run C++ code you write. Each program fundamentally consists of a setup and a loop.

You can sort of think of setup as your ‘main’ method, but you exit it immediately and start looping.

One thing that you need to remember with an embedded program is that your program never stops; it runs until the device doesn’t have power, you reset the board, or you upload a new program. There is no ‘exit’.

In an Arduino program you can do a lot of the things you’d expect from a C++ program, like having additional C++ code files (files with a .cpp extension work just fine). You do have a lot less memory to play with though; the processor on my Arduino only has 6KB of RAM. As someone who tends to work on web applications that consume hundreds of MB, it’s a bit jarring, but 6KB is actually plenty for my needs.

When you want to run your program, you compile it as you would with a normal program; the Arduino components on your desktop then upload the program to the device (over the USB connection) and store it in Flash memory. Again, you can’t have massive applications; my board has 48KB of Flash to fit the program in.

My First Arduino Program

First off, I’m going to make an LED flash. Big stuff, I know. My Arduino (and most of them I think), have a built-in LED that you can turn on and off from your program.

Let’s make a new project in VS Code. Create a new folder somewhere and open it in VS Code.

Then, to start a new ‘project’, run Arduino: Initialize from the command palette. This created a blank app.ino file and let me select my board, which got me started.

I found that I got an intellisense error in the created ino file:

Clicking on the ‘fix-it’ bulb took me to the C++ include path settings:

After a quick search of the Arduino install directory for ‘pgmspace.h’, turned out I was missing an additional include path:

C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\**

After I added that to the list with the necessary extra backslashes, closed and then re-opened my app.ino file, no more squiggles, and I get nice intellisense.

Controlling an LED

My built-in LED is on PIN #13 of the processor (I used the Arduino Board reference to check what was available); in your program there is an LED_BUILTIN constant already supplied that references it.

A bit of embedded basics here; everything you do in embedded programming is basically turning pins on and off on your processor.

The big arrow is pointing to a pin

Want to turn on an LED? Set the ‘level’ of the pin connected to the LED to HIGH (which means it has voltage on it). To turn it off, set the level to LOW (which means it has no/negligible voltage on it).

I had to configure the LED pin to be an output pin in my setup method, and then set it HIGH and LOW in my loop. Put some delays in there and you have a flickering LED!

You can upload the program from the command palette (or CTRL+ALT+U).

GIF of an LED blinking (very exciting!)

You might encounter one or more problems getting that program downloaded (like I did):

COM Port

I had problems getting the COM Port (the Arduino connects as a virtual COM Port over USB) to work first time, so my code wouldn’t upload. I had to go into the main Arduino IDE and install the package it recommended for my board. This installed different drivers, which changed the COM Port to Atmel rather than Microsoft.

I also had to go into Windows Device Manager, go into the settings, and change the COM Port to not be the default COM3. Only then would it actually upload.

Select the Right Board!

Pro Tip – make sure you pick the right board in the VSCode footer, and select the processor.

Mine is the Arduino Uno WiFI Rev2, with the A4809 processor.

Hello World

Next step, I want to do the tried and tested programming exercise of writing Hello World to the ‘Console’.

The Arduino doesn’t have a console to write to in the normal sense you might be familiar with; what it can do however is write to the Serial connection you use to upload your programs, and the Arduino extension in VS Code can display it.

More embedded basics; Remember how I said that everything in embedded programming is turning pins on (HIGH) and off (LOW)? Well, that’s true of writing text to a Serial connection too, but we do it extremely quickly.

Luckily, we don’t have to do all the pin changes ourselves (phew); there are functions already supplied by the Arduino libraries that will do this for us.

When we configure our Serial port, we need to set its ‘baud’, or speed. This tells the Serial code how fast we want to send characters. 9600 baud means that we are sending approximately 9600 bytes/characters per second. Whatever is ‘listening’ on the other end needs to know the speed, otherwise you’ll just get junk out.

So once we’ve setup our Serial Port, in our loop, once per second we print our Hello World to the Serial port.

Once you’ve copied that code into your app.ino, upload the program as you would normally.

Once you’ve uploaded your program, it’s initially a bit anti-climatic, nothing is obviously happening. To see the output, we need to open the Serial Monitor. Click on the little connection logo in the VS Code footer:

This will bring up the Serial Monitor. At this point, you will probably just be getting nonsense, so you will want to change the ‘baud’ for the Serial Monitor to 9600.

Once you’ve done that, you should get your Hello World being displayed!

Next Steps

Ok, so that’s it for now. Subsequent posts will cover:

  • Wiring up my sensors and reading analogue values.
  • Using the WiFi module to sent HTTP requests
  • Using the data I collect!

Implementing a shared resource lock in your load-balanced application with MongoDB in C#

In your load-balanced cluster of nice, performant application servers, you may occasionally find that there is an outside resource that requires access be synchronised between each server in the cluster (ideally not too often, because it’s a pain, but there you go).

We encountered this recently when dealing with multiple clients trying to access and update a reporting component we interface with via our application. Each client issued HTTP API requests to the application that would:

  1. Read a resource from the reporting system (by the ID)
  2. Do something
  3. Update the resource

The problem is that no two tasks should be allowed to get past step 1 at the same time for a given named resource. This is starting to look pretty familiar, right?

We see this in a single-server multi-threaded model sometimes (although not too often hopefully; I find synchronous locks are generally bad for performance if used too liberally in web requests).

The problem with the above code is that it only locks a resource in the current process; a different HTTP request, routed to a different server by the load balancer, would happily acquire it’s own lock.

Establishing a distributed lock

What we need now is to lock the resource across our entire cluster, not just on the one server.

We use MongoDB for general shared state between servers in our cluster, so I looked into how to use MongoDB to also synchronise access to our resource between the application servers.

Luckily, it turns out that by using existing MongoDB functionality, this is pretty straightforward to create a short-lived resource lock.

I’ve written this solution in C#, using the official MongoDB C# client, but there’s no reason this wouldn’t apply to a different MongoDB client implementation in any language.

Want to jump to the end?

Create the Collection

First up, I want to create a new MongoDB collection to hold my locks. I’ll create a model and then get an instance of that collection.

That’s pretty basic stuff, you’d have to do that generally to access any MongoDB collection.

Next we’re going to add the function used to acquire a lock, AcquireLock. This method is responsible for the ‘spin’ or retry on the lock, waiting to acquire it.

The AcquireLock method:

  1. Creates a ‘lock id’ from the resource id.
  2. Creates a ‘DistributedLock’ object, which is where the locking mechanism happens (more on this in a moment).
  3. Attempts to get the lock in a while loop.
  4. Waits up to a 10 second timeout to acquire the lock, attempting again every 100ms.
  5. Returns the DistributedLock once the lock is acquired (but only as an IDisposable).

Next let’s look at what is going on inside the DistributedLock class.


The DistributedLock class is responsible for the actual MongoDB commands, and attempting the lock.

Let’s break down what happens here. The AttemptGetLock method issues a FindOneAndUpdate MongoDB command that does the following:

  1. Looks for a record with an ID the same as the provided lock ID.
  2. If it finds it, it returns it without doing anything (because our update is only a SetOnInsert, not a Set).
  3. If it doesn’t find it, it creates a new document (because IsUpsert is true), with the expected ID.

We’ve set the ReturnDocument option to ‘Before’, because that means the result of the FindOneAndUpdateAsync is null if there was no existing lock document. If there was no existing document, there will be one now, and we have acquired the lock!

When you dispose of the lock, we just delete the lock document from the collection, and hey presto, the lock has been released, and the next thread to try to get the lock will do so.

Using It

Because the AcquireLock method returns an IDisposable (via a Task), you can just use a ‘using’ statement in a similar manner to how you would use the ‘lock’ statement.

Do you see that await inside the using definition? Right, do not forget to use it. If you do forget, all hell will break loose, because Task<IDisposable> also implements IDisposable! So you’ll end up instantly entering the using block, and then disposing of the task afterwards at some point while the lock attempts are happening. This causes many bad things.

Make sense? Good. Unfortunately, we’re not quite done…

Handing Concurrent Lock Attempts

So, while the above version of DistributedLock works pretty well most of the time, at some point it will inevitably throw an exception when handling multiple concurrent lock attempts:

Duplicate keys…

Why does this happen? Well, the upsert functionality in findAndModify is not technically atomic in the way you might expect; the find and the insert are different operations internally to MongoDB, so two lock attempts might both attempt to insert a record.

When that happens, the default ID index on the MongoDB collection will throw an E11000 duplicate key error.

This is actually OK; one of the threads that attempted to acquire a lock will get it (the first one to complete the insert), and the second one will get an exception, so we just need to amend our code to say that the thread with the exception failed to get the lock.

Handling a Crash

The last problem we have to solve is what happens if one of the application servers crashes part-way through a piece of work?

If a thread has a lock, but the server crashes or is otherwise disconnected from MongoDB, it can’t release the resource, meaning no-one else will ever be able to take a lock on the resource.

We need to put in some safeguard against this that allows the lock to eventually be released even if the application isn’t able to do it correctly.

To do this, we can use one of my favourite MongoDB features, TTL Indexes, which allows MongoDB to ‘age out’ records automatically, based on a column that contains an ‘expiry’ time.

Let’s update the original LockModel with an expiry property, and add a TTL index to our collection.

In the above index creation instruction, I’m specifying an ExpireAfter of TimeSpan.Zero, meaning that as soon as the DateTime specified in ExpireAt of the lock document passes, the document will be deleted.

Finally, we’ll update the MongoDB FindOneAndUpdate instruction in DistributedLock to set the ExpireAt property to the current time plus 1 minute.

Now, if a lock isn’t released after 1 minute, it will automatically be cleaned up by MongoDB, and another thread will be able to acquire the lock.

Notes on TTL Indexes and Timeouts

  • The TTL index is not a fast way of releasing these locks; the accuracy on it is low, because by default the MongoDB thread that checks for expired documents only runs once every 60 seconds.
    We’re using it as a safety net for an edge case, rather than a predictable mechanism. If you need a faster recovery than that 60 second window, then you may need to look for an alternative solution.
  • You may notice that I’m using DateTime.UtcNow for the ExpireAt value, rather than DateTime.Now; this is because I have had a variety of problems storing C# DateTimes with a timezone in MongoDB in a reliable way, so I tend to prefer storing UTC values whenever possible (especially when it’s not a user-entered value).

Sample Project

I’ve created a github repo with an ASP.NET Core project at https://github.com/alistairjevans/mongodb-locks that has a complete implementation of the above, with an example API controller that outputs timing information for the lock acquisition.