![]() |
VOOZH | about |
dotnet add package AsyncEnumerator --version 4.0.2
NuGet\Install-Package AsyncEnumerator -Version 4.0.2
<PackageReference Include="AsyncEnumerator" Version="4.0.2" />
<PackageVersion Include="AsyncEnumerator" Version="4.0.2" />Directory.Packages.props
<PackageReference Include="AsyncEnumerator" />Project file
paket add AsyncEnumerator --version 4.0.2
#r "nuget: AsyncEnumerator, 4.0.2"
#:package AsyncEnumerator@4.0.2
#addin nuget:?package=AsyncEnumerator&version=4.0.2Install as a Cake Addin
#tool nuget:?package=AsyncEnumerator&version=4.0.2Install as a Cake Tool
1: How to use this library?
See examples above. You can the core code and lots of useful extension methods in the Dasync.Collections namespace.
2: Using CancellationToken
using Dasync.Collections;
IAsyncEnumerable<int> ProduceNumbers()
{
return new AsyncEnumerable<int>(async yield => {
await FooAsync(yield.CancellationToken);
});
}
3: Always remember about ConfigureAwait(false)
To avoid performance degradation and possible dead-locks in ASP.NET or WPF applications (or any SynchronizationContext-dependent environment), you should always put ConfigureAwait(false) in your await statements:
using Dasync.Collections;
IAsyncEnumerable<int> GetValues()
{
return new AsyncEnumerable<int>(async yield =>
{
await FooAsync().ConfigureAwait(false);
// Yes, it's even needed for 'yield.ReturnAsync'
await yield.ReturnAsync(123).ConfigureAwait(false);
});
}
4: Clean-up on incomplete enumeration
Imagine such situation:
using Dasync.Collections;
IAsyncEnumerable<int> ReadValuesFromQueue()
{
return new AsyncEnumerable<int>(async yield =>
{
using (var queueClient = CreateQueueClient())
{
while (true)
{
var message = queueClient.DequeueMessageAsync();
if (message == null)
break;
await yield.ReturnAsync(message.Value);
}
}
});
}
Task<int> ReadFirstValueOrDefaultAsync()
{
return ReadValuesFromQueue().FirstOrDefaultAsync();
}
The FirstOrDefaultAsync method will try to read first value from the IAsyncEnumerator, and then will just dispose it. However, disposing AsyncEnumerator does not mean that the queueClient in the lambda function will be disposed automatically as well, because async methods are just state machines which need somehow to go to a particular state to do the clean-up.
To provide such behavior, when you dispose an AsyncEnumerator before you reach the end of enumeration, it will tell to resume your async lambda function (at await yield.ReturnAsync()) with the AsyncEnumerationCanceledException (derives from OperationCanceledException). Having such exception in your lambda method will break normal flow of enumeration and will go to terminal state of the underlying state machine, what will do the clean-up, i.e. dispose the queueClient in this case. You don't need (and shouldn't) catch that exception type, because it's handled internally by AsyncEnumerator. The same exception is thrown when you call yield.Break().
There is another option to do the cleanup on Dispose:
using Dasync.Collections;
IAsyncEnumerator<int> GetQueueEnumerator()
{
var queueClient = CreateQueueClient();
return new AsyncEnumerable<int>(async yield =>
{
while (true)
{
var message = queueClient.DequeueMessageAsync();
if (message == null)
break;
await yield.ReturnAsync(message.Value);
}
},
onDispose: () => queueClient.Dispose());
}
5: Why is GetAsyncEnumeratorAsync async?
The IAsyncEnumerable.GetAsyncEnumeratorAsync() method is async and returns a Task<IAsyncEnumerator>, where the current implementation of AsyncEnumerable always runs that method synchronously and just returns an instance of AsyncEnumerator. Having interfaces allows you to do your own implementation, where classes mentioned above are just helpers. The initial idea was to be able to support database-like scenarios, where GetAsyncEnumeratorAsync() executes a query first (what internally returns a pointer), and the MoveNextAsync() enumerates through rows (by using that pointer).
6: Returning IAsyncEnumerable vs IAsyncEnumerator
When you implement a method that returns an async-enumerable collection you have a choice to return either IAsyncEnumerable or IAsyncEnumerator - the constructors of the helper classes AsyncEnumerable and AsyncEnumerator are absolutely identical. Both interfaces have same set of useful extension methods, like ForEachAsync.
When you create an 'enumerable', you create a factory that produces 'enumerators', i.e. you can enumerate through a collection many times. On the other hand, creating an 'enumerator' is needed when you can through a collection only once.
7: Where is Reset or ResetAsync?
The Reset method must not be on the IEnumerator interface, and should be considered as deprecated. Create a new enumerator instead. This is the reason why the 'oneTimeUse' flag was removed in version 2 of this library.
8: How can I do synchronous for-each enumeration through IAsyncEnumerable?
You can use extension methods like IAsyncEnumerable.ToEnumerable() to use built-in foreach enumeration, BUT you should never do that! The general idea of this library is to avoid thread-blocking calls on worker threads, where converting an IAsyncEnumerable to IEnumerable will just defeat the whole purpose of this library. This is the reason why such synchronous extension methods are marked with [Obsolete] attribute.
9: What's the difference between ForEachAsync and ParallelForEachAsync?
The ForEachAsync allows you to go through a collection and perform an action on every single item in sequential manner. On the other hand, ParallelForEachAsync allows you to run the action on multiple items at the same time where the sequential
order of completion is not guaranteed. For the latter, the degree of the parallelism is controlled by the maxDegreeOfParalellism
argument, however it does not guarantee to spin up the exact amount of threads, because it depends on the thread pool size and its occupancy at a moment of time. Such parallel approach is much better than trying to create a task for an action for every single item on the collection and then awaiting on all of them with Task.WhenAll, because it adds less overhead to the runtime, better with memory usage, and helps with throttling-sensitive scenarios.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp1.0 netcoreapp1.0 was computed. netcoreapp1.1 netcoreapp1.1 was computed. netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard1.4 netstandard1.4 is compatible. netstandard1.5 netstandard1.5 was computed. netstandard1.6 netstandard1.6 was computed. netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 is compatible. |
| .NET Framework | net45 net45 is compatible. net451 net451 was computed. net452 net452 was computed. net46 net46 was computed. net461 net461 is compatible. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen30 tizen30 was computed. tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Universal Windows Platform | uap uap was computed. uap10.0 uap10.0 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on AsyncEnumerator:
| Package | Downloads |
|---|---|
|
NBitcoin.Indexer
Library for querying data indexed by NBitcoin.Indexer on Azure Storage |
|
|
Libplanet.Net
A peer-to-peer networking layer based on Libplanet. |
|
|
Elect.Core
Comprehensive collection of essential utilities and extension methods for .NET Core applications. Includes helpers for configuration, dependency injection, serialization, HTTP operations, and common programming patterns. |
|
|
Halforbit.RecordStreams
Package Description |
|
|
Halforbit.RecordStreams.BlobStorage
Package Description |
Showing the top 12 popular GitHub repositories that depend on AsyncEnumerator:
| Repository | Stars |
|---|---|
|
Flangvik/TeamFiltration
TeamFiltration is a cross-platform framework for enumerating, spraying, exfiltrating, and backdooring O365 AAD accounts
|
|
|
n00mkrad/text2image-gui
Somewhat modular text2image GUI, initially just for Stable Diffusion
|
|
|
mertcreates/Steam-Library-Manager
Open source utility to manage Steam, Origin and Uplay libraries in ease of use with multi library support. ||| Steam Games Database: https://stmstat.com
|
|
|
planetarium/libplanet
Blockchain in C#/.NET for on-chain, decentralized gaming
|
|
|
fmbot-discord/fmbot
.fmbot is a social Discord bot that provides music statistics for you and your friends.
|
|
|
Texnomic/SecureDNS
Secure, Modern, Fully-Featured, All-In-One Cross-Architecture & Cross-Platform DNS Server Using .NET 10
|
|
|
rayshift/translatefgo
FGO Translation Project
|
|
|
gregyjames/OctaneDownloader
A high performance, multi-threaded C# file download library.
|
|
|
Dasync/Dasync
Every developer deserves the right of creating microservices without using any framework 🤍
|
|
|
isbeorn/nina
N.I.N.A. (Nighttime Imaging 'N' Astronomy) - Advanced astrophotography sequencing software for Windows, supporting full automation of imaging sessions.
|
|
|
topnguyen/Elect
The collection of utilities, best practice and fluent method for .NET Core
|
|
|
MightyOrm/Mighty
A new, small, dynamic micro-ORM. Highly compatible with Massive, but with many essential new features.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.2 | 23,474,645 | 12/4/2019 |
| 4.0.1 | 227,029 | 10/22/2019 |
| 4.0.0 | 50,557 | 10/18/2019 |
| 3.1.0 | 177,442 | 9/23/2019 |
| 2.2.2 | 2,643,765 | 1/27/2019 |
| 2.2.1 | 1,576,886 | 5/29/2018 |
| 2.2.0 | 61,271 | 5/18/2018 |
| 2.1.1 | 2,629,101 | 1/20/2018 |
| 2.1.0 | 359,160 | 5/22/2017 |
| 2.0.1 | 69,997 | 2/13/2017 |
| 1.5.0 | 9,129 | 2/12/2017 |
| 1.4.2 | 6,733 | 2/6/2017 |
| 1.3.0 | 6,868 | 1/20/2017 |
| 1.2.3 | 17,940 | 1/6/2017 |
| 1.2.2 | 7,432 | 12/11/2016 |
4.0.0: Use interfaces from Microsoft.Bcl.AsyncInterfaces package in NET Standard 2.0.
3.1.0: Add support for NET Standard 2.1, consolidate interface with Microsoft's implementation.
2.2.0: New extension methods: SelectMany, Append, Prepend, OfType, Concat, Distinct, ToDictionaryAsync, ToLookupAsync, AggregateAsync.
2.1.0: New extension methods: Batch, UnionAll, Single, SingleOrDefault, DefaultIfEmpty, Cast.
2.0.0: Revise design of the library: same features, but slight paradigm shift and interface breaking changes.
1.5.0: Add support for .NET Standard, minor improvements.
1.4.2: Add finalizer to AsyncEnumerator and call Dispose in ForEachAsync and ParallelForEachAsync extension methods.
1.4.0: Add new generic type AsyncEnumeratorWithState for performance optimization.
Now IAsyncEnumerator<T> is covariant.
Add ForEachAsync, ParallelForeachAsync, and LINQ-style extension methods for IAsyncEnumerator.
1.2.1: New Linq-style extension methods in System.Collections.Async namespace.
1.1.0: Add ParallelForEachAsync extension methods for IEnumerable<T> and IAsyncEnumerable<T> in System.Collections.Async namespace.