Chaining async/await - c#

I developing many algorithms that did most of the threading by themselves by using regular Threads. The approach was always as following
float[] GetData(int requestedItemIndex)
With the method above and index was pushed into some messages queue that was processed by the thread of the inidividual algorithm. So in the end the interface of the algorithm was like this:
public abstract class AlgorithmBase
{
private readonly AlgorithmBase Parent;
private void RequestQueue()
{
}
public float[] GetData(int requestedItemIndex) => Parent.GetData(requestedItemIndex);
}
The example is very primitive, but just to get the clue. The problem is that I can chain algorithms which currently works fine with my solution. As you can see every GetData calls another GetData of a parent algorithm. This can of course get more complex and of course there needs to be a final parent as data source, otherwise I would get StackOverflowExceptions.
Now I try to change this behavior by using async/await. My question here is that if I rewrite my code I would get something like this:
public abstract class AlgorithmBase
{
private readonly AlgorithmBase Parent;
public async Task<float[]> GetDataAsync(int requestedItemIndex, CancellationToken token = default)
{
var data = await Parent.GetDataAsync(requestedItemIndex);
return await Task.Run<float[]>(async () => ProcessData());
}
}
Now, I have chained the algorithms, any every new algorithm spans another Task, which can be quite time consuming when this is done many times.
So my questions is if there is a way where the next task can be embedded in the already running task, by using the defines interface?

There is no need to explicitly use Task.Run. You should avoid that, and leave that choice to the consumer of AlgorithmBase class.
So, you can quite similarly implement async version, in which Task object will be propagated from parents to childred:
public abstract class AlgorithmBase
{
private readonly AlgorithmBase Parent;
private void RequestQueue()
{
}
public Task<float[]> GetDataAsync(int requestedItemIndex)
=> Parent.GetDataAsync(requestedItemIndex);
}
Eventually, some "parent" will implement GetDataAsync, in the same manner as synchronous counterpart.
public class SortAlgorithm : AlgorithmBase
{
public override async Task<float[]> GetDataAsync(int requestedItemIndex)
{
// asynchronously get data
var data = await Parent.GetDataAsync(requestedItemIndex);
// synchronously process data and return from asynchronous method
return this.ProcessData(data);
}
private float[] ProcessData(float[] data)
{
}
}
In the end, consumer of SortAlogirthm can decide whether to await it, or just fire-and-forget it.
var algo = new SortAlgorithm();
// asynchronously wait until it's finished
var data = await algo.GetDataAsync(1);
// start processing without waiting for the result
algo.GetDataAsync(1);
// not needed - GetDataAsync already returns Task, Task.Run is not needed in this case
Task.Run(() => algo.GetDataAsync(1));

When awaiting in library code you normally want to avoid capturing and restoring the context each and every time, especially if you are awaiting in a loop. So to improve the performance of your library consider using .ConfigureAwait(false) on all awaits.

Related

How to Pause/Resume an asynchronous worker, without incurring memory allocation overhead?

I have an asynchronous method that contains an endless while loop. This loop is paused and resumed frequently by the main thread of the program. For this purpose I am using currently the PauseTokenSource class from the Nito.AsyncEx package:
private readonly PauseTokenSource _pausation = new();
private async Task StartWorker()
{
while (true)
{
await _pausation.Token.WaitWhilePausedAsync();
DoSomething();
}
}
This works pretty well, but I noticed that around 100 bytes are allocated each time the PauseTokenSource is paused and resumed. Since this happens many times per second, I am searching for a way to eliminate this overhead. My idea is to replace the PauseTokenSource with a home-made pausation mechanism that has a WaitWhilePausedAsync method that returns a ValueTask instead of Task. To make the implementation allocation-free, the ValueTask should be backed by something that implements the IValueTaskSource interface. Here is my current (failed) attempt to implement this mechanism:
public class Pausation : IValueTaskSource
{
private ManualResetValueTaskSourceCore<bool> _source;
private bool _paused;
public Pausation() => _source.RunContinuationsAsynchronously = true;
public void Pause()
{
_paused = true;
_source.Reset();
}
public void Resume()
{
_paused = false;
_source.SetResult(default);
}
public ValueTask WaitWhilePausedAsync()
{
if (!_paused) return ValueTask.CompletedTask;
return new ValueTask(this, _source.Version);
}
void IValueTaskSource.GetResult(short token)
{
_source.GetResult(token);
}
ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
{
return _source.GetStatus(token);
}
void IValueTaskSource.OnCompleted(Action<object> continuation, object state,
short token, ValueTaskSourceOnCompletedFlags flags)
{
_source.OnCompleted(continuation, state, token, flags);
}
}
My Pausation class is based on the ManualResetValueTaskSourceCore<T> struct, which is supposed to simplify the most common IValueTaskSource implementations. Apparently I am doing something wrong, because when my worker awaits the WaitWhilePausedAsync method, it crashes with an InvalidOperationException.
My question is: How can I fix the Pausation class, so that it works correctly? Should I add more state beyond the _paused field? Am I calling the ManualResetValueTaskSourceCore<T> methods in the wrong places? I am asking either for detailed fixing instructions, or for a complete and working implementation.
Specifics: The Pausation class is intended to be used in a single worker - single controller scenario. There is only one asynchronous worker (the StartWorker method), and only one controller thread issues Pause and Resume commands. Also there is no need for cancellation support. The termination of the worker is handled independently by a CancellationTokenSource (removed from the above snippet for brevity). The only functionality that is needed is the Pause, Resume and WaitWhilePausedAsync methods. The only requirement is that it works correctly, and it doesn't allocate memory.
A runnable online demo of my worker - controller scenario can be found here.
Output with the Nito.AsyncEx.PauseTokenSource class:
Controller loops: 112,748
Worker loops: 84, paused: 36 times
Output with my Pausation class:
Controller loops: 117,397
Unhandled exception. System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.GetStatus(Int16 token)
at Program.Pausation.System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(Int16 token)
at Program.<>c__DisplayClass0_0.<<Main>g__StartWorker|0>d.MoveNext()
I believe you're misunderstanding Reset. ManualResetValueTaskSourceCore<T>.Reset is nothing at all like ManualResetEvent.Reset. For ManualResetValueTaskSourceCore<T>, Reset means "the previous operation has completed, and now I want to reuse the value task, so change the version". So, it should be called after GetResult (i.e., after the paused code is done awaiting), not within Pause. The easiest way to encapsulate this IMO is to Reset the state immediately before returning the ValueTask.
Similarly, your code shouldn't call SetResult unless there's a value task already returned. ManualResetValueTaskSourceCore<T> is really designed around sequential operations pretty strictly, and having a separate "controller" complicates things. You could probably get it working by keeping track of whether or not the consumer is waiting, and only attempting to complete if there is one:
public class Pausation : IValueTaskSource
{
private ManualResetValueTaskSourceCore<bool> _source;
private readonly object _mutex = new();
private bool _paused;
private bool _waiting;
public Pausation() => _source.RunContinuationsAsynchronously = true;
public void Pause()
{
lock (_mutex)
_paused = true;
}
public void Resume()
{
var wasWaiting = false;
lock (_mutex)
{
wasWaiting = _waiting;
_paused = _waiting = false;
}
if (wasWaiting)
_source.SetResult(default);
}
public ValueTask WaitWhilePausedAsync()
{
lock (_mutex)
{
if (!_paused) return ValueTask.CompletedTask;
_waiting = true;
_source.Reset();
return new ValueTask(this, _source.Version);
}
}
void IValueTaskSource.GetResult(short token)
{
_source.GetResult(token);
}
ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
{
return _source.GetStatus(token);
}
void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
{
_source.OnCompleted(continuation, state, token, flags);
}
}
I fixed some of the obvious race conditions using a mutex, but I can't guarantee there aren't more subtle ones remaining. It will certainly be limited to a single controller and single consumer, at least.
You may have misunderstood the purpose of ValueTask. Stephen Toub breaks down why it was introduced here: https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/
But the most relevant bit of information is that ValueTask does not allocate iff the asynchronous method completes synchronously and successfully.
If it does need to complete asynchronously, there is no getting around needing to allocate a Task class due to the state machine in the background. So this may need another solution entirely.

Calling Entity Framework async code, synchronously, within a lock

I have an async method which will load some info from the database via Entity Framework.
In one circumstance I want to call that code synchronously from within a lock.
Do I need two copies of the code, one async, one not, or is there a way of calling the async code synchronously?
For example something like this:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
new Test().Go();
}
}
public class Test
{
private object someLock = new object();
public void Go()
{
lock(someLock)
{
Task<int> task = Task.Run(async () => await DoSomethingAsync());
var result = task.Result;
}
}
public async Task<int> DoSomethingAsync()
{
// This will make a database call
return await Task.FromResult(0);
}
}
Edit: as a number of the comments are saying the same thing, I thought I'd elaborate a little
Background: normally, trying to do this is a bad idea. Lock and async are polar opposites as documented in lots of places, there's no reason to have an async call in a lock.
So why do it here? I can make the database call synchronously but that requires duplicating some methods which isn't ideal. Ideally the language would let you call the same method synchronously or asynchronously
Scenario: this is a Web API. The application starts, a number of Web API calls execute and they all want some info that's in the database that's provided by a service provider dedicated for that purpose (i.e. a call added via AddScoped in the Startup.cs). Without something like a lock they will all try to get the info from the database. EF Core is only relevant in that every other call to the database is async, this one is the exception.
You simply cannot use a lock with asynchronous code; the entire point of async/await is to switch away from a strict thread-based model, but lock aka System.Monitor is entirely thread focused. Frankly, you also shouldn't attempt to synchronously call asynchronous code; that is simply not valid, and no "solution" is correct.
SemaphoreSlim makes a good alternative to lock as an asynchronous-aware synchronization primitve. However, you should either acquire/release the semaphore inside the async operation in your Task.Run, or you should make your Go an asynchronous method, i.e. public async Task GoAsync(), and do the same there; of course, at that point it becomes redundant to use Task.Run, so: just execute await DoSomethingAsync() directly:
private readonly SemaphoreSlim someLock = new SemaphoreSlim(1, 1);
public async Task GoAsync()
{
await someLock.WaitAsync();
try
{
await DoSomethingAsync();
}
finally
{
someLock.Release();
}
}
If the try/finally bothers you; perhaps cheat!
public async Task GoAsync()
{
using (await someLock.LockAsync())
{
await DoSomethingAsync();
}
}
with
internal static class SemaphoreExtensions
{
public static ValueTask<SemaphoreToken> LockAsync(this SemaphoreSlim semaphore)
{
// try to take synchronously
if (semaphore.Wait(0)) return new(new SemaphoreToken(semaphore));
return SlowLockAsync(semaphore);
static async ValueTask<SemaphoreToken> SlowLockAsync(SemaphoreSlim semaphore)
{
await semaphore.WaitAsync().ConfigureAwait(false);
return new(semaphore);
}
}
}
internal readonly struct SemaphoreToken : IDisposable
{
private readonly SemaphoreSlim _semaphore;
public void Dispose() => _semaphore?.Release();
internal SemaphoreToken(SemaphoreSlim semaphore) => _semaphore = semaphore;
}

Migrating to Async: Repository

I have a large codebase using my repositories that all implement IRespository and I'm implementing async versions of the methods:
T Find(id);
Task<T> FindAsync(id);
...etc...
There are several kinds of repository. The simplest is based on an immutable collection where the universe of entities is small enough to merit loading them all at once from the DB. This load happens the first time anyone calls any of the IRepository methods. Find(4), for example, will trigger the load if it hasn't happened already.
I've implemented this with Lazy < T >. Very handy and has been working for years.
I can't go cold-turkey on Async so I have to add Async alongside the sync versions. My problem is, I don't know which will be called first - a sync or async method on the repository.
I don't know how to declare my Lazy - if I do it as I've always done it,
Lazy<MyCollection<T>>
then loading it won't be async when FindAsync() is called first. On the other hand, if I go
Lazy<Task<MyCollection<T>>>
This would be great for FindAsync() but how will a synchronous method trigger the initial load w/o running afoul of Mr. Cleary's warnings about deadlock from calling Task.Result?
Thank you for your time!
The problem with Lazy<T> is that there's only one factory method. What you really want is a synchronous factory method if the first call is synchronous, and an asynchronous factory method if the first call is asynchronous. Lazy<T> won't do that for you, and AFAIK there's nothing else built-in that offers these semantics either.
You can, however, build one yourself:
public sealed class SyncAsyncLazy<T>
{
private readonly object _mutex = new object();
private readonly Func<T> _syncFunc;
private readonly Func<Task<T>> _asyncFunc;
private Task<T> _task;
public SyncAsyncLazy(Func<T> syncFunc, Func<Task<T>> asyncFunc)
{
_syncFunc = syncFunc;
_asyncFunc = asyncFunc;
}
public T Get()
{
return GetAsync(true).GetAwaiter().GetResult();
}
public Task<T> GetAsync()
{
return GetAsync(false);
}
private Task<T> GetAsync(bool sync)
{
lock (_mutex)
{
if (_task == null)
_task = DoGetAsync(sync);
return _task;
}
}
private async Task<T> DoGetAsync(bool sync)
{
return sync ? _syncFunc() : await _asyncFunc().ConfigureAwait(false);
}
}
Or you can just use this pattern without encapsulating it:
private readonly object _mutex = new object();
private Task<MyCollection<T>> _collectionTask;
private Task<MyCollection<T>> LoadCollectionAsync(bool sync)
{
lock (_mutex)
{
if (_collectionTask == null)
_collectionTask = DoLoadCollectionAsync(sync);
return _collectionTask;
}
}
private async Task<MyCollection<T>> DoLoadCollectionAsync(bool sync)
{
if (sync)
return LoadCollectionSynchronously();
else
return await LoadCollectionAsynchronously();
}
The "bool sync" pattern is one Stephen Toub showed me recently. AFAIK there's no blogs or anything about it yet.
Tasks will run only once but you can await on them as many times as you want and you can also call Wait() or Result on them after completed and that won't block.
Asynchronous methods are converted into a state machine that schedules the code after each await to run after the awaitable is completed. However, there's an optimization where if the awaitble is already completed the code runs immediately. So, awaiting on completed awaiters bears little overhead.
For those small in-memory repositories, you can return a completed Task using Task.FromResult. And you can cache any Task and await it any time.
how will a synchronous method trigger the initial load w/o running afoul of Mr. Cleary's warnings about deadlock from calling Task.Result?
You can use the synchronous version and use Task.FromResult to load your Lazy<Task<MyCollection<T>>>. If this lazily async operation is exposed to the outside, it may confuse since it will block. If this is an internal single call situation, I would go with:
private Lazy<Task<MyCollection<T>>> myCollection = new Lazy<Task<MyCollection<T>>>(() =>
{
var collection = myRepo.GetCollection<T>();
return Task.FromResult(collection);
}

Running Class Methods in BackgroundWorker

I have a Class which has about a dozen Methods in it. Most of the Methods execute and complete rather quickly. However two off the Methods can, on occasion, take quite some time to run their course. So from looking around, I think I want to run them in a BackgroundWorker.
But I am just not getting my head around the details of this yet. I am a bit of a noob.
My main form for the application;
namespace EncodeDecode
{
public partial class EnDecoder : Form
{
CodeMachine coder = new CodeMachine();
// char[] letters = new char[94 + 33];
List<string> words = new List<string>();
}
}
public class CodeMachine
{
public bool Encode() // This takes a while
{
}
public bool Decode() // This takes a while
{
}
public bool Load() // This is quick
{
}
..... // The rest are quick too
.....
}
}
So, how do I run the two lengthy Methods inside the coder instance of my class, in the BackgroundWorker?
Maybe you can make your methods async and await for their results, so something like:
CodeMachine coder = new CodeMachine();
// run this async and await response (will not block the UI)
// it will sort of use it as a checkpoint to continue from
await coder.EncodeAsync();
Then in your CodeMachine you make an async method that returns the result:
public class CodeMachine
{
// naming convention has it ending with Async
public async Task<bool> EncodeAsync()
{
// do something that takes a while here ....
}
}
Here is more info.
The BackgroundWorker is a class that can be used to execute a single method on a separate thread. Its an easy way to use threading for beginners in my opinion.
From what your asking it looks like your looking to asynchronously run the methods that take a long time.
I usually do this with delegates and BeginInvoke because thats what I'm used to and my shop just recently moved to .Net 4.0.
Dimitar's answer with use of tasks would probably be the simpler way to go. Good luck.

How to initialize an object using async-await pattern

I'm trying to follow RAII pattern in my service classes, meaning that when an object is constructed, it is fully initialized. However, I'm facing difficulties with asynchronous APIs. The structure of class in question looks like following
class ServiceProvider : IServiceProvider // Is only used through this interface
{
public int ImportantValue { get; set; }
public event EventHandler ImportantValueUpdated;
public ServiceProvider(IDependency1 dep1, IDependency2 dep2)
{
// IDependency1 provide an input value to calculate ImportantValue
// IDependency2 provide an async algorithm to calculate ImportantValue
}
}
I'm also targeting to get rid of side-effects in ImportantValue getter, to make it thread-safe.
Now users of ServiceProvider will create an instance of it, subscribe to an event of ImportantValue change, and get the initial ImportantValue. And here comes the problem, with the initial value. Since the ImportantValue is calculated asynchronously, the class cannot be fully initialized in constructor. It may be okay to have this value as null initially, but then I need to have some place where it will be calculated first time. A natural place for that could be the ImportantValue's getter, but I'm targeting to make it thread-safe and with no side-effects.
So I'm basically stuck with these contradictions. Could you please help me and offer some alternative? Having value initialized in constructor while nice is not really necessary, but no side-effects and thread-safety of property is mandatory.
Thanks in advance.
EDIT: One more thing to add. I'm using Ninject for instantiation, and as far as I understand, it doesn't support async methods to create a binding. While approach with initiating some Task-based operation in constructor will work, I cannot await its result.
I.e. two next approaches (offered as answers so far) will not compile, since Task is returned, not my object:
Kernel.Bind<IServiceProvider>().ToMethod(async ctx => await ServiceProvider.CreateAsync())
or
Kernel.Bind<IServiceProvider>().ToMethod(async ctx =>
{
var sp = new ServiceProvider();
await sp.InitializeAsync();
})
Simple binding will work, but I'm not awaiting the result of asynchronous initialization started in constructor, as proposed by Stephen Cleary:
Kernel.Bind<IServiceProvider>().To<ServiceProvider>();
... and that's not looking good for me.
I have a blog post that describes several approaches to async construction.
I recommend the asynchronous factory method as described by Reed, but sometimes that's not possible (e.g., dependency injection). In these cases, you can use an asynchronous initialization pattern like this:
public sealed class MyType
{
public MyType()
{
Initialization = InitializeAsync();
}
public Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
await Task.Delay(100);
}
}
You can then construct the type normally, but keep in mind that construction only starts the asynchronous initialization. When you need the type to be initialized, your code can do:
await myTypeInstance.Initialization;
Note that if Initialization is already complete, execution (synchronously) continues past the await.
If you do want an actual asynchronous property, I have a blog post for that, too. Your situation sounds like it may benefit from AsyncLazy<T>:
public sealed class MyClass
{
public MyClass()
{
MyProperty = new AsyncLazy<int>(async () =>
{
await Task.Delay(100);
return 13;
});
}
public AsyncLazy<int> MyProperty { get; private set; }
}
One potential option would be to move this to a factory method instead of using a constructor.
Your factory method could then return a Task<ServiceProvider>, which would allow you to perform the initialization asynchronously, but not return the constructed ServiceProvider until ImportantValue has been (asynchronously) computed.
This would allow your users to write code like:
var sp = await ServiceProvider.CreateAsync();
int iv = sp.ImportantValue; // Will be initialized at this point
This is a slight modification to #StephenCleary pattern of async initialization.
The difference being the caller doesn't need to 'remember' to await the InitializationTask, or even know anything about the initializationTask (in fact it is now changed to private).
The way it works is that in every method that uses the initialized data there is an initial call to await _initializationTask. This returns instantly the second time around - because the _initializationTask object itself will have a boolean set (IsCompleted which the 'await' mechanism checks) - so don't worry about it initializing multiple times.
The only catch I'm aware of is you mustn't forget to call it in every method that uses the data.
public sealed class MyType
{
public MyType()
{
_initializationTask = InitializeAsync();
}
private Task _initializationTask;
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
_customers = await LoadCustomersAsync();
}
public async Task<Customer> LookupCustomer(string name)
{
// Waits to ensure the class has been initialized properly
// The task will only ever run once, triggered initially by the constructor
// If the task failed this will raise an exception
// Note: there are no () since this is not a method call
await _initializationTask;
return _customers[name];
}
// one way of clearing the cache
public void ClearCache()
{
InitializeAsync();
}
// another approach to clearing the cache, will wait until complete
// I don't really see a benefit to this method since any call using the
// data (like LookupCustomer) will await the initialization anyway
public async Task ClearCache2()
{
await InitializeAsync();
}
}
You could use my AsyncContainer IoC container which supports the exact same scenario as you.
It also supports other handy scenarios such as async initializers, run-time conditional factories, depend on async and sync factory functions
//The email service factory is an async method
public static async Task<EmailService> EmailServiceFactory()
{
await Task.Delay(1000);
return new EmailService();
}
class Service
{
//Constructor dependencies will be solved asynchronously:
public Service(IEmailService email)
{
}
}
var container = new Container();
//Register an async factory:
container.Register<IEmailService>(EmailServiceFactory);
//Asynchronous GetInstance:
var service = await container.GetInstanceAsync<Service>();
//Safe synchronous, will fail if the solving path is not fully synchronous:
var service = container.GetInstance<Service>();
I know this is an old question, but it's the first which appears on Google and, quite frankly, the accepted answer is a poor answer. You should never force a delay just so you can use the await operator.
A better approach to an initialization method:
private async Task<bool> InitializeAsync()
{
try{
// Initialize this instance.
}
catch{
// Handle issues
return await Task.FromResult(false);
}
return await Task.FromResult(true);
}
This will use the async framework to initialize your object, but then it will return a boolean value.
Why is this a better approach? First off, you're not forcing a delay in your code which IMHO totally defeats the purpose of using the async framework. Second, it's a good rule of thumb to return something from an async method. This way, you know if your async method actually worked/did what it was supposed to. Returning just Task is the equivalent of returning void on a non-async method.
I have a variation of Stephen Cleary's example of an asynchronous initialization pattern. You could encapsulate the Initialization property and await it in the class methods. In this case, the client code will not need to await the initialization task.
public class ClassWithAsyncInit
{
public ClassWithAsyncInit()
{
Initialization = InitializeAsync();
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// your async init code
}
public async Task FirstMethod()
{
await Initialization;
// ... other code
}
}
The drawback is that it's not convenient if you have a lot of methods in your class and need to await the Initialization task in each one. But sometimes it is okay. Let's say you have a simple interface for saving some JSON objects:
public IDataSaver
{
void Save(string json);
}
And you need to implement it for a database with the asynchronous initialization logic. Considering that you would have only one public method it makes sense to encapsulate the Initialization property and await it in the Save method:
public class SomeDbDataSaver: IDataSaver
{
protected DatabaseClient DbClient { get; set; }
public SomeDbDataSaver()
{
DbClient = new DatabaseClient();
Initialization = InitializeAsync(); // start off the async init
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
await DbClient.CreateDatabaseIfNotExistsAsync("DatabaseName");
}
public async Task Save(string json)
{
await Initialization;
// ... code for saving a data item to the database
}
}

Categories

Resources