EnumerableAsyncProcessor
EnumerableAsyncProcessor is an innovative library designed for developers who need to handle multiple asynchronous tasks in a flexible manner. Whether you want to process tasks one at a time, in batches, with rate limits, or fully concurrently, this library provides the tools to manage these operations efficiently without having to delve into complex boilerplate code.
Purpose of the Library
The main goal of EnumerableAsyncProcessor is to give developers control over the speed and frequency at which asynchronous operations are executed. It acknowledges scenarios where you might need to adjust the pace of these operations, whether for performance optimization, resource management, or simply due to external restrictions like API request limits.
Key Features
Rate Limited Parallel Processor
This feature allows for the execution of asynchronous operations in parallel while respecting a set limit on the number of concurrent tasks. Once a task finishes, a new one is initiated, ensuring that the total number running never exceeds the specified limit. This strikes a balance between processing speed and resource utilization.
Usage Example:
var ids = Enumerable.Range(0, 5000).ToList();
// Executing tasks with results
var results = await AsyncProcessorBuilder.WithItems(ids)
.SelectAsync(id => DoSomethingAndReturnSomethingAsync(id), CancellationToken.None)
.ProcessInParallel(levelOfParallelism: 100);
// Executing tasks without needing results
await AsyncProcessorBuilder.WithItems(ids)
.ForEachAsync(id => DoSomethingAsync(id), CancellationToken.None)
.ProcessInParallel(levelOfParallelism: 100);
Timed Rate Limited Parallel Processor
This feature functions similarly to the Rate Limited Processor but adds the dimension of time. It enforces a limit on how many operations can be executed over a specified timeframe. This is particularly helpful for operations subject to rate limits, such as API calls with a maximum requests-per-second constraint.
Usage Example:
var results = await AsyncProcessorBuilder.WithItems(ids)
.SelectAsync(id => DoSomethingAndReturnSomethingAsync(id), CancellationToken.None)
.ProcessInParallel(levelOfParallelism: 100, TimeSpan.FromSeconds(1));
One At A Time Processor
Designed for simplicity and safety, this method processes tasks sequentially. Only one task is executed at any given time, making it the slowest but safest choice where task interdependencies exist or system resources are exceptionally constrained.
Batch Processor
With batch processing, tasks are grouped and run together. The next set of tasks will only start once all tasks in the current batch have completed. This method can be effective for managing resources but may introduce delays if even one task in the batch is slow.
Parallel Processor
For maximum speed, the Parallel Processor executes all tasks simultaneously as fast as possible. While this can be the quickest method, it risks overwhelming system resources, leading to potential bottlenecks.
Getting Started
EnumerableAsyncProcessor requires .NET 6 and can be easily installed using Nuget:
Install-Package EnumerableAsyncProcessor
Processor Methods
Developers can retrieve results in various forms depending on their needs—whether it's processing them as they complete with IAsyncEnumerable<TOutput>
, or collecting all finished results at once with Task<TOutput[]>
.
Conclusion
EnumerableAsyncProcessor provides a rich set of methods to handle asynchronous tasks efficiently and effectively. Whether you're aiming for parallel execution or carefully controlled task rates, this library offers solutions to meet those needs while minimizing the overhead of manual management. Consider using this library in your next project to streamline your asynchronous task processing and avoid common pitfalls associated with task parallelization.