Skip to content

Commit 2ee881b

Browse files
author
Oren (electricessence)
committed
Added readme.
1 parent 8b92713 commit 2ee881b

File tree

3 files changed

+338
-3
lines changed

3 files changed

+338
-3
lines changed

Open.ChannelExtensions/README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Open.ChannelExtensions
2+
3+
A set of extensions for optimizing/simplifying System.Threading.Channels usage.
4+
5+
## Highlights
6+
7+
Being able to define an asynchronous pipeline with best practice usage using simple expressive syntax:
8+
9+
```cs
10+
await Channel
11+
.CreateBounded<T>(10)
12+
.SourceAsync(source /* IEnumerable<Task<T>> */)
13+
.PipeAsync(
14+
maxConcurrency: 2,
15+
capacity: 5,
16+
transform: asyncTransform01)
17+
.Pipe(transform02, /* capacity */ 3)
18+
.ReadAllAsync(finalTransformedValue => {
19+
// Do something async with each final value.
20+
});
21+
```
22+
23+
```cs
24+
await source /* IEnumerable<T> */
25+
.ToChannel(boundedSize: 10, singleReader: true)
26+
.PipeAsync(asyncTransform01, /* capacity */ 5)
27+
.Pipe(
28+
maxConcurrency: 2,
29+
capacity: 3,
30+
transform: transform02)
31+
.ReadAll(finalTransformedValue => {
32+
// Do something with each final value.
33+
});
34+
```
35+
36+
## Examples
37+
38+
### Reading (until the channel is closed)
39+
40+
#### One by one read each entry from the channel
41+
42+
```cs
43+
await channel.ReadAll(
44+
entry => { /* Processing Code */ });
45+
```
46+
47+
```cs
48+
await channel.ReadAll(
49+
(entry, index) => { /* Processing Code */ });
50+
```
51+
52+
```cs
53+
await channel.ReadAllAsync(
54+
async entry => { await /* Processing Code */ });
55+
```
56+
57+
```cs
58+
await channel.ReadAllAsync(
59+
async (entry, index) => { await /* Processing Code */ });
60+
```
61+
62+
#### Read concurrently each entry from the channel
63+
64+
```cs
65+
await channel.ReadAllConcurrently(
66+
maxConcurrency,
67+
entry => { /* Processing Code */ });
68+
```
69+
70+
```cs
71+
await channel.ReadAllConcurrentlyAsync(
72+
maxConcurrency,
73+
async entry => { await /* Processing Code */ });
74+
```
75+
76+
### Writing
77+
78+
If `complete` is `true`, the channel will be closed when the source is empty.
79+
80+
#### Dump a source enumeration into the channel
81+
82+
```cs
83+
// source can be any IEnumerable<T>.
84+
await channel.WriteAll(source, complete: true);
85+
```
86+
87+
```cs
88+
// source can be any IEnumerable<Task<T>> or IEnumerable<ValueTask<T>>.
89+
await channel.WriteAllAsync(source, complete: true);
90+
```
91+
92+
#### Synchronize reading from the source and process the results concurrently
93+
94+
```cs
95+
// source can be any IEnumerable<Task<T>> or IEnumerable<ValueTask<T>>.
96+
await channel.WriteAllConcurrentlyAsync(
97+
maxConcurrency, source, complete: true);
98+
```
99+
100+
### Pipelining / Transforming
101+
102+
#### Transform and buffer entries
103+
104+
```cs
105+
// Transform values in a source channel to new unbounded channel.
106+
var transformed = channel.Pipe(
107+
async value => /* transformation */);
108+
```
109+
110+
```cs
111+
// Transform values in a source channel to new unbounded channel with a max concurrency of X.
112+
const X = 4;
113+
var transformed = channel.Pipe(
114+
X, async value => /* transformation */);
115+
```
116+
117+
```cs
118+
// Transform values in a source channel to new bounded channel bound of N entries.
119+
const N = 5;
120+
var transformed = channel.Pipe(
121+
async value => /* transformation */, N);
122+
```
123+
124+
```cs
125+
// Transform values in a source channel to new bounded channel bound of N entries with a max concurrency of X.
126+
const X = 4;
127+
const N = 5;
128+
var transformed = channel.Pipe(
129+
X, async value => /* transformation */, N);
130+
131+
// or
132+
transformed = channel.Pipe(
133+
maxConcurrency: X,
134+
capacity: N,
135+
transform: async value => /* transformation */);
136+
```

docs/README.html

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<!DOCTYPE html>
2+
<!--[if IE]><![endif]-->
3+
<html>
4+
5+
<head>
6+
<meta charset="utf-8">
7+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8+
<title>Open.ChannelExtensions </title>
9+
<meta name="viewport" content="width=device-width">
10+
<meta name="title" content="Open.ChannelExtensions ">
11+
<meta name="generator" content="docfx 2.47.0.0">
12+
13+
<link rel="shortcut icon" href="favicon.ico">
14+
<link rel="stylesheet" href="styles/docfx.vendor.css">
15+
<link rel="stylesheet" href="styles/docfx.css">
16+
<link rel="stylesheet" href="styles/main.css">
17+
<meta property="docfx:navrel" content="">
18+
<meta property="docfx:tocrel" content="">
19+
20+
21+
22+
</head>
23+
<body data-spy="scroll" data-target="#affix" data-offset="120">
24+
<div id="wrapper">
25+
<header>
26+
27+
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
28+
<div class="container">
29+
<div class="navbar-header">
30+
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
31+
<span class="sr-only">Toggle navigation</span>
32+
<span class="icon-bar"></span>
33+
<span class="icon-bar"></span>
34+
<span class="icon-bar"></span>
35+
</button>
36+
37+
<a class="navbar-brand" href="index.html">
38+
<img id="logo" class="svg" src="logo.svg" alt="">
39+
</a>
40+
</div>
41+
<div class="collapse navbar-collapse" id="navbar">
42+
<form class="navbar-form navbar-right" role="search" id="search">
43+
<div class="form-group">
44+
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
45+
</div>
46+
</form>
47+
</div>
48+
</div>
49+
</nav>
50+
51+
<div class="subnav navbar navbar-default">
52+
<div class="container hide-when-search" id="breadcrumb">
53+
<ul class="breadcrumb">
54+
<li></li>
55+
</ul>
56+
</div>
57+
</div>
58+
</header>
59+
<div role="main" class="container body-content hide-when-search">
60+
<div class="article row grid">
61+
<div class="col-md-10">
62+
<article class="content wrap" id="_content" data-uid="">
63+
<h1 id="openchannelextensions">Open.ChannelExtensions</h1>
64+
65+
<p>A set of extensions for optimizing/simplifying System.Threading.Channels usage.</p>
66+
<h2 id="highlights">Highlights</h2>
67+
<p>Being able to define an asynchronous pipeline with best practice usage using simple expressive syntax:</p>
68+
<pre><code class="lang-cs">await Channel
69+
.CreateBounded&lt;T&gt;(10)
70+
.SourceAsync(source /* IEnumerable&lt;Task&lt;T&gt;&gt; */)
71+
.PipeAsync(
72+
maxConcurrency: 2,
73+
capacity: 5,
74+
transform: asyncTransform01)
75+
.Pipe(transform02, /* capacity */ 3)
76+
.ReadAllAsync(finalTransformedValue =&gt; {
77+
// Do something async with each final value.
78+
});
79+
</code></pre><pre><code class="lang-cs">await source /* IEnumerable&lt;T&gt; */
80+
.ToChannel(boundedSize: 10, singleReader: true)
81+
.PipeAsync(asyncTransform01, /* capacity */ 5)
82+
.Pipe(
83+
maxConcurrency: 2,
84+
capacity: 3,
85+
transform: transform02)
86+
.ReadAll(finalTransformedValue =&gt; {
87+
// Do something with each final value.
88+
});
89+
</code></pre><h2 id="examples">Examples</h2>
90+
<h3 id="reading-until-the-channel-is-closed">Reading (until the channel is closed)</h3>
91+
<h4 id="one-by-one-read-each-entry-from-the-channel">One by one read each entry from the channel</h4>
92+
<pre><code class="lang-cs">await channel.ReadAll(
93+
entry =&gt; { /* Processing Code */ });
94+
</code></pre><pre><code class="lang-cs">await channel.ReadAll(
95+
(entry, index) =&gt; { /* Processing Code */ });
96+
</code></pre><pre><code class="lang-cs">await channel.ReadAllAsync(
97+
async entry =&gt; { await /* Processing Code */ });
98+
</code></pre><pre><code class="lang-cs">await channel.ReadAllAsync(
99+
async (entry, index) =&gt; { await /* Processing Code */ });
100+
</code></pre><h4 id="read-concurrently-each-entry-from-the-channel">Read concurrently each entry from the channel</h4>
101+
<pre><code class="lang-cs">await channel.ReadAllConcurrently(
102+
maxConcurrency,
103+
entry =&gt; { /* Processing Code */ });
104+
</code></pre><pre><code class="lang-cs">await channel.ReadAllConcurrentlyAsync(
105+
maxConcurrency,
106+
async entry =&gt; { await /* Processing Code */ });
107+
</code></pre><h3 id="writing">Writing</h3>
108+
<p>If <code>complete</code> is <code>true</code>, the channel will be closed when the source is empty.</p>
109+
<h4 id="dump-a-source-enumeration-into-the-channel">Dump a source enumeration into the channel</h4>
110+
<pre><code class="lang-cs">// source can be any IEnumerable&lt;T&gt;.
111+
await channel.WriteAll(source, complete: true);
112+
</code></pre><pre><code class="lang-cs">// source can be any IEnumerable&lt;Task&lt;T&gt;&gt; or IEnumerable&lt;ValueTask&lt;T&gt;&gt;.
113+
await channel.WriteAllAsync(source, complete: true);
114+
</code></pre><h4 id="synchronize-reading-from-the-source-and-process-the-results-concurrently">Synchronize reading from the source and process the results concurrently</h4>
115+
<pre><code class="lang-cs">// source can be any IEnumerable&lt;Task&lt;T&gt;&gt; or IEnumerable&lt;ValueTask&lt;T&gt;&gt;.
116+
await channel.WriteAllConcurrentlyAsync(
117+
maxConcurrency, source, complete: true);
118+
</code></pre><h3 id="pipelining--transforming">Pipelining / Transforming</h3>
119+
<h4 id="transform-and-buffer-entries">Transform and buffer entries</h4>
120+
<pre><code class="lang-cs">// Transform values in a source channel to new unbounded channel.
121+
var transformed = channel.Pipe(
122+
async value =&gt; /* transformation */);
123+
</code></pre><pre><code class="lang-cs">// Transform values in a source channel to new unbounded channel with a max concurrency of X.
124+
const X = 4;
125+
var transformed = channel.Pipe(
126+
X, async value =&gt; /* transformation */);
127+
</code></pre><pre><code class="lang-cs">// Transform values in a source channel to new bounded channel bound of N entries.
128+
const N = 5;
129+
var transformed = channel.Pipe(
130+
async value =&gt; /* transformation */, N);
131+
</code></pre><pre><code class="lang-cs">// Transform values in a source channel to new bounded channel bound of N entries with a max concurrency of X.
132+
const X = 4;
133+
const N = 5;
134+
var transformed = channel.Pipe(
135+
X, async value =&gt; /* transformation */, N);
136+
137+
// or
138+
transformed = channel.Pipe(
139+
maxConcurrency: X,
140+
capacity: N,
141+
transform: async value =&gt; /* transformation */);
142+
</code></pre></article>
143+
</div>
144+
145+
<div class="hidden-sm col-md-2" role="complementary">
146+
<div class="sideaffix">
147+
<div class="contribution">
148+
<ul class="nav">
149+
<li>
150+
<a href="https://github.com/electricessence/Open.ChannelExtensions/blob/master/Open.ChannelExtensions/README.md/#L1" class="contribution-link">Improve this Doc</a>
151+
</li>
152+
</ul>
153+
</div>
154+
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
155+
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
156+
</nav>
157+
</div>
158+
</div>
159+
</div>
160+
</div>
161+
162+
<footer>
163+
<div class="grad-bottom"></div>
164+
<div class="footer">
165+
<div class="container">
166+
<span class="pull-right">
167+
<a href="#top">Back to top</a>
168+
</span>
169+
170+
<span>Generated by <strong>DocFX</strong></span>
171+
</div>
172+
</div>
173+
</footer>
174+
</div>
175+
176+
<script type="text/javascript" src="styles/docfx.vendor.js"></script>
177+
<script type="text/javascript" src="styles/docfx.js"></script>
178+
<script type="text/javascript" src="styles/main.js"></script>
179+
</body>
180+
</html>

docs/manifest.json

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
"source_base_path": "D:/Users/essence/Development/- GitHub/Open.ChannelExtensions/Open.ChannelExtensions",
44
"xrefmap": "xrefmap.yml",
55
"files": [
6+
{
7+
"type": "Conceptual",
8+
"source_relative_path": "README.md",
9+
"output": {
10+
".html": {
11+
"relative_path": "README.html",
12+
"hash": "z1Fnrm1HvGaiPwADLMFvsg=="
13+
}
14+
},
15+
"is_incremental": false,
16+
"version": ""
17+
},
618
{
719
"type": "ManagedReference",
820
"source_relative_path": "api/Open.ChannelExtensions.Extensions.yml",
@@ -49,18 +61,25 @@
4961
"skipped_file_count": 0
5062
},
5163
"processors": {
52-
"TocDocumentProcessor": {
64+
"ConceptualDocumentProcessor": {
5365
"can_incremental": false,
54-
"details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.",
66+
"details": "Processor ConceptualDocumentProcessor disable incremental build because last build doesn't contain version .",
5567
"incrementalPhase": "build",
56-
"total_file_count": 0,
68+
"total_file_count": 1,
5769
"skipped_file_count": 0
5870
},
5971
"ManagedReferenceDocumentProcessor": {
6072
"can_incremental": true,
6173
"incrementalPhase": "build",
6274
"total_file_count": 2,
6375
"skipped_file_count": 2
76+
},
77+
"TocDocumentProcessor": {
78+
"can_incremental": false,
79+
"details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.",
80+
"incrementalPhase": "build",
81+
"total_file_count": 0,
82+
"skipped_file_count": 0
6483
}
6584
}
6685
},

0 commit comments

Comments
 (0)