Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/open-net-libraries/open.channelextensions
A set of extensions for optimizing/simplifying System.Threading.Channels usage.
https://github.com/open-net-libraries/open.channelextensions
async channel channels dotnet extensions tasks threading
Last synced: 1 day ago
JSON representation
A set of extensions for optimizing/simplifying System.Threading.Channels usage.
- Host: GitHub
- URL: https://github.com/open-net-libraries/open.channelextensions
- Owner: Open-NET-Libraries
- License: mit
- Created: 2018-10-18T04:15:12.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-11-18T16:39:36.000Z (2 months ago)
- Last Synced: 2025-01-19T06:28:05.769Z (2 days ago)
- Topics: async, channel, channels, dotnet, extensions, tasks, threading
- Language: C#
- Homepage: https://open-net-libraries.github.io/Open.ChannelExtensions/api/Open.ChannelExtensions.Extensions.html#methods
- Size: 908 KB
- Stars: 439
- Watchers: 13
- Forks: 26
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Open.ChannelExtensions
[![NuGet](https://img.shields.io/nuget/v/Open.ChannelExtensions.svg?style=flat)](https://www.nuget.org/packages/Open.ChannelExtensions/)
A set of extensions for optimizing/simplifying System.Threading.Channels usage.
[Click here for detailed documentation.](https://open-net-libraries.github.io/Open.ChannelExtensions/api/Open.ChannelExtensions.Extensions.html#methods)
## Highlights
### Read & Write
*With optional concurrency levels.*
* Reading all entries in a channel.
* Writing all entries from a source to a channel.
* Piping (consuming) all entries to a buffer (channel).
* `.AsAsyncEnumerable()` (`IAsyncEnumerable`) support for .NET Standard 2.1+ and .NET Core 3+### Special `ChannelReader` Operations
* `Filter`: reads from the channel until a match is found.
* `Transform`: applies a transform function upon successfully reading an item from the channel.
* `Batch`: attempts to group items into a `List` (or a `Queue`) before being available for reading.
* `Join`: combines batches into a single channel.---
## Installation```nuget
Install-Package Open.ChannelExtensions
```
---## Examples
Being able to define an asynchronous pipeline with best practice usage using simple expressive syntax:
```cs
await Channel
.CreateBounded(10)
.SourceAsync(source /* IEnumerable> */)
.PipeAsync(
maxConcurrency: 2,
capacity: 5,
transform: asyncTransform01)
.Pipe(transform02, /* capacity */ 3)
.ReadAllAsync(finalTransformedValue => {
// Do something async with each final value.
});
``````cs
await source /* IEnumerable */
.ToChannel(boundedSize: 10, singleReader: true)
.PipeAsync(asyncTransform01, /* capacity */ 5)
.Pipe(
maxConcurrency: 2,
capacity: 3,
transform: transform02)
.ReadAll(finalTransformedValue => {
// Do something with each final value.
});
```### Reading (until the channel is closed)
#### One by one read each entry from the channel
```cs
await channel.ReadAll(
entry => { /* Processing Code */ });
``````cs
await channel.ReadAll(
(entry, index) => { /* Processing Code */ });
``````cs
await channel.ReadAllAsync(
async entry => { await /* Processing Code */ });
``````cs
await channel.ReadAllAsync(
async (entry, index) => { await /* Processing Code */ });
```#### Read concurrently each entry from the channel
```cs
await channel.ReadAllConcurrently(
maxConcurrency,
entry => { /* Processing Code */ });
``````cs
await channel.ReadAllConcurrentlyAsync(
maxConcurrency,
async entry => { await /* Processing Code */ });
```### Writing
If `complete` is `true`, the channel will be closed when the source is empty.
#### Dump a source enumeration into the channel
```cs
// source can be any IEnumerable.
await channel.WriteAll(source, complete: true);
``````cs
// source can be any IEnumerable> or IEnumerable>.
await channel.WriteAllAsync(source, complete: true);
```#### Synchronize reading from the source and process the results concurrently
```cs
// source can be any IEnumerable> or IEnumerable>.
await channel.WriteAllConcurrentlyAsync(
maxConcurrency, source, complete: true);
```### Filter & Transform
Both of these extensions operate synchronously after an item is read from the channel.
> Any predicate or selector function must trap errors of the downstream read will fail and data may not be recoverable.```cs
// Filter and transform when reading.
channel.Reader
.Filter(predicate) // .Where()
.Transform(selector) // .Select()
.ReadAllAsync(async value => {/*...*/});
```### Batching
```cs
values.Reader
.Batch(10 /*batch size*/) // Groups into List.
.WithTimeout(1000) // Any non-empty batches are flushed every second.
.ReadAllAsync(async batch => {/*...*/});
```### Joining
The inverse of batching.
```cs
batches.Reader
.Join() // Combines the batches into a single channel.
.ReadAllAsync(async value => {/*...*/});
```### Pipelining / Transforming
#### Transform and buffer entries
```cs
// Transform values in a source channel to new unbounded channel.
var transformed = channel.Pipe(
async value => /* transformation */);
``````cs
// Transform values in a source channel to new unbounded channel with a max concurrency of X.
const int X = 4;
var transformed = channel.Pipe(
X, async value => /* transformation */);
``````cs
// Transform values in a source channel to new bounded channel bound of N entries.
const int N = 5;
var transformed = channel.Pipe(
async value => /* transformation */, N);
``````cs
// Transform values in a source channel to new bounded channel bound of N entries with a max concurrency of X.
const int X = 4;
const int N = 5;
var transformed = channel.Pipe(
X, async value => /* transformation */, N);// or
transformed = channel.Pipe(
maxConcurrency: X,
capacity: N,
transform: async value => /* transformation */);
```