Reputation: 87
I needed to implement a simple transaction. For that case my transaction class implements the IDisposable interface. That way I can use my transaction class within a using statement and if any error happens within that scope, everything get's rolled back when the transaction is disposed.
using (var transaction = new Transaction())
{
// do some stuff
}
The "do some stuff" also includes some client/server connections etc.
Now I roll back everything if "do some stuff" raised any error.
public async void Dispose(){ // roll back everything on error }
That probably includes to cleanup some resources on a server where I need to call asynchronous operations. That leads to my question: can I safely just use the async keyword for my Dispose() implementation to enable the await keyword within its implementation? Or could this lead probably to race conditions due to synchronisation context issues or something like that?
Upvotes: 7
Views: 7958
Reputation: 2139
As Gusdor already mentioned in his answer, you cannot simply add the async
keyword to the Dispose()
method of the IDisposable
interface.
However, since C# 8.0, a new interface for async disposal is available: IAsyncDisposable
With this you can implement true async disposal. To see how it works, have a look at this excellent article from Microsoft: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync
Upvotes: 2
Reputation: 3489
How about calling Task.Run(...). It queues the specified work to run on the ThreadPool.
public void Dispose()
{
if (_thereWasAnError)
{
Task.Run(async () => await RollbackAsync()).Wait();
}
}
Upvotes: 5
Reputation: 14334
You can only use await
when the method returns Task
, Task<T>
or another implementation of an awaitable.
IDisposable
does not define a Task Dispose()
method. You can always write your own, but it will not be called when you exit the using
block.
Depending on the locking mechanism in your resource, you may risk race conditions with an async void
(avoid those!).
Upvotes: 2