From b2dbffb081f861c5fc59d9c344dd606fdc0dd724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Hompus?= Date: Thu, 9 Nov 2023 21:48:04 +0100 Subject: [PATCH 1/2] Provide Threading.Tasks.Dataflow package readme --- .../src/PACKAGE.md | 126 ++++++++++++++++-- 1 file changed, 113 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md b/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md index f15811be3267ab..e17c6e1eed7c17 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md @@ -2,43 +2,143 @@ +Provides dataflow components that are collectively referred to as the *TPL Dataflow Library*. +This dataflow model promotes actor-based programming by providing in-process message passing for coarse-grained dataflow and pipelining tasks. +Note: This package is part of the larger *Task Parallel library* and is designed to help increase the robustness of concurrency-enabled applications. ## Key Features -* -* -* +* Foundation for message passing and parallelizing CPU-intensive and I/O-intensive applications that have high throughput and low latency. +* Provides multiple block types for various dataflow operations (e.g., `BufferBlock`, `ActionBlock`, `TransformBlock`). +* Blocks support linking to form *networks*, allowing for the creation of complex processing topologies. ## How to Use +This sample demonstrates a dataflow pipeline that downloads the book "The Iliad of Homer" from a website and searches the text to match individual words with words that reverse the first word's characters. + +```csharp +using System.Net; +using System.Threading.Tasks.Dataflow; + +// Setup blocks + +// Downloads the requested resource as a string. +TransformBlock downloadString = new TransformBlock(async uri => +{ + Console.WriteLine("Downloading '{0}'...", uri); + + return await new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip }).GetStringAsync(uri); +}); + +// Separates the specified text into an array of words. +TransformBlock createWordList = new TransformBlock(text => +{ + Console.WriteLine("Creating word list..."); + + // Remove common punctuation by replacing all non-letter characters with a space character. + char[] tokens = text.Select(c => char.IsLetter(c) ? c : ' ').ToArray(); + text = new string(tokens); + + // Separate the text into an array of words. + return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); +}); + +// Removes short words and duplicates. +TransformBlock filterWordList = new TransformBlock(words => +{ + Console.WriteLine("Filtering word list..."); + + return words + .Where(word => word.Length > 3) + .Distinct() + .ToArray(); +}); + +// Finds all words in the specified collection whose reverse also exists in the collection. +TransformManyBlock findReversedWords = new TransformManyBlock(words => +{ + Console.WriteLine("Finding reversed words..."); + + var wordsSet = new HashSet(words); + + return from word in words.AsParallel() + let reverse = new string(word.Reverse().ToArray()) + where word != reverse && wordsSet.Contains(reverse) + select word; +}); + +// Prints the provided reversed words to the console. +ActionBlock printReversedWords = new ActionBlock(reversedWord => +{ + Console.WriteLine("Found reversed words {0}/{1}", reversedWord, new string(reversedWord.Reverse().ToArray())); +}); + + +// Connect the dataflow blocks to form a pipeline. +var linkOptions = new DataflowLinkOptions { PropagateCompletion = true }; + +downloadString.LinkTo(createWordList, linkOptions); +createWordList.LinkTo(filterWordList, linkOptions); +filterWordList.LinkTo(findReversedWords, linkOptions); +findReversedWords.LinkTo(printReversedWords, linkOptions); + +// Post data to the pipeline, "The Iliad of Homer" by Homer. +downloadString.Post("http://www.gutenberg.org/cache/epub/16452/pg16452.txt"); + +// Mark the head of the pipeline as complete. +downloadString.Complete(); + +// Wait for the last block in the pipeline to process all messages. +printReversedWords.Completion.Wait(); + +// Output: +// Downloading 'http://www.gutenberg.org/cache/epub/16452/pg16452.txt'... +// Creating word list... +// Filtering word list... +// Finding reversed words... +// Found reversed words parts/strap +// Found reversed words deer/reed +// Found reversed words deem/meed +// Found reversed words flow/wolf +// ... + +``` + +More details can be found on [Dataflow (Task Parallel Library)](https://learn.microsoft.com/dotnet/standard/parallel-programming/dataflow-task-parallel-library) and [Walkthrough: Creating a Dataflow Pipeline](https://learn.microsoft.com/dotnet/standard/parallel-programming/walkthrough-creating-a-dataflow-pipeline) pages. + ## Main Types The main types provided by this library are: -* `` -* `` -* `` +* `System.Threading.Tasks.Dataflow.ISourceBlock` +* `System.Threading.Tasks.Dataflow.ITargetBlock` +* `System.Threading.Tasks.Dataflow.IPropagatorBlock` +* `System.Threading.Tasks.Dataflow.ActionBlock` +* `System.Threading.Tasks.Dataflow.BatchBlock` +* `System.Threading.Tasks.Dataflow.BatchedJoinBlock` +* `System.Threading.Tasks.Dataflow.BroadcastBlock` +* `System.Threading.Tasks.Dataflow.BufferBlock` +* `System.Threading.Tasks.Dataflow.JoinBlock` +* `System.Threading.Tasks.Dataflow.TransformBlock` +* `System.Threading.Tasks.Dataflow.TransformManyBlock` +* `System.Threading.Tasks.Dataflow.WriteOnceBlock` ## Additional Documentation -* [Conceptual documentation](https://learn.microsoft.com/dotnet/standard/serialization/**LIBRARYNAME**/overview) -* [API documentation](https://learn.microsoft.com/dotnet/api/**LIBRARYNAME**) - -## Related Packages - - +* [Conceptual documentation](https://learn.microsoft.com/dotnet/standard/parallel-programming/dataflow-task-parallel-library) +* [API documentation](https://learn.microsoft.com/dotnet/api/system.threading.tasks.dataflow) ## Feedback & Contributing -System.Threading.Tasks.Dataflow is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). \ No newline at end of file +System.Threading.Tasks.Dataflow is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). From ab41cdb198e04593e086919fc1b40659207904fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Hompus?= Date: Mon, 8 Jan 2024 20:22:14 +0100 Subject: [PATCH 2/2] Apply feedback --- .../src/PACKAGE.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md b/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md index e17c6e1eed7c17..594817775ac10f 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/PACKAGE.md @@ -5,15 +5,13 @@ Provides dataflow components that are collectively referred to as the *TPL Dataflow Library*. This dataflow model promotes actor-based programming by providing in-process message passing for coarse-grained dataflow and pipelining tasks. -Note: This package is part of the larger *Task Parallel library* and is designed to help increase the robustness of concurrency-enabled applications. - ## Key Features * Foundation for message passing and parallelizing CPU-intensive and I/O-intensive applications that have high throughput and low latency. * Provides multiple block types for various dataflow operations (e.g., `BufferBlock`, `ActionBlock`, `TransformBlock`). -* Blocks support linking to form *networks*, allowing for the creation of complex processing topologies. +* Dataflow blocks support linking to form *networks*, allowing you to create complex processing topologies. ## How to Use @@ -23,8 +21,12 @@ This sample demonstrates a dataflow pipeline that downloads the book "The Iliad ```csharp using System.Net; +using System.Text.RegularExpressions; using System.Threading.Tasks.Dataflow; +var nonLetterRegex = new Regex(@"\P{L}", RegexOptions.Compiled); +var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip }); + // Setup blocks // Downloads the requested resource as a string. @@ -32,7 +34,7 @@ TransformBlock downloadString = new TransformBlock createWordList = new TransformBlock char.IsLetter(c) ? c : ' ').ToArray(); - text = new string(tokens); + text = nonLetterRegex.Replace(text, " "); // Separate the text into an array of words. return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); @@ -55,7 +56,6 @@ TransformBlock filterWordList = new TransformBlock word.Length > 3) - .Distinct() .ToArray(); }); @@ -66,7 +66,7 @@ TransformManyBlock findReversedWords = new TransformManyBlock< var wordsSet = new HashSet(words); - return from word in words.AsParallel() + return from word in wordsSet let reverse = new string(word.Reverse().ToArray()) where word != reverse && wordsSet.Contains(reverse) select word;