Praise for Concurrency in C# Cookbook “The next big thing in computing is making massive parallelism accessible to mere mortals. Developers have more power available to us than ever before, but expressing concurrency is still a challenge for many. Stephen turns his attention to this problem, helping us all better understand concurrency, threading, reactive programming models, parallelism, and much more in an easy-to-read but complete reference.” — Scott Hanselman Principal Program Manager, ASP.NET and Azure Web Tools, Microsoft “The breadth of techniques covered and the cookbook format make this the ideal reference book for modern .NET concurrency.” — Jon Skeet Senior Software Engineer at Google “Stephen Cleary has established himself as a key expert on asynchrony and parallelism in C#. This book clearly and concisely conveys the most important points and principles developers need to understand to get started and be successful with these technologies.” — Stephen Toub Principal Architect, Microsoft Concurrency in C# Cookbook Stephen Cleary Concurrency in C# Cookbook by Stephen Cleary Copyright © 2014 Stephen Cleary. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/ institutional sales department: 800-998-9938 or [email protected]. Editors: Brian MacDonald and Rachel Roumeliotis Indexer: Ellen Troutman Production Editor: Nicole Shelby Cover Designer: Randy Comer Copyeditor: Charles Roumeliotis Interior Designer: David Futato Proofreader: Amanda Kersey Illustrator: Rebecca Demarest June 2014: First Edition Revision History for the First Edition: 2014-05-14: First release See http://oreilly.com/catalog/errata.csp?isbn=9781449367565 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Concurrency in C# Cookbook, the picture of a common palm civet, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc. was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein. ISBN: 978-1-449-36756-5 [Q] Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Concurrency: An Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1. Introduction to Concurrency 1 1.2. Introduction to Asynchronous Programming 3 1.3. Introduction to Parallel Programming 7 1.4. Introduction to Reactive Programming (Rx) 10 1.5. Introduction to Dataflows 12 1.6. Introduction to Multithreaded Programming 14 1.7. Collections for Concurrent Applications 15 1.8. Modern Design 15 1.9. Summary of Key Technologies 15 2. Async Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.1. Pausing for a Period of Time 18 2.2. Returning Completed Tasks 20 2.3. Reporting Progress 21 2.4. Waiting for a Set of Tasks to Complete 22 2.5. Waiting for Any Task to Complete 25 2.6. Processing Tasks as They Complete 26 2.7. Avoiding Context for Continuations 30 2.8. Handling Exceptions from async Task Methods 31 2.9. Handling Exceptions from async Void Methods 32 3. Parallel Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.1. Parallel Processing of Data 35 3.2. Parallel Aggregation 37 3.3. Parallel Invocation 39 3.4. Dynamic Parallelism 40 iii 3.5. Parallel LINQ 42 4. Dataflow Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 4.1. Linking Blocks 46 4.2. Propagating Errors 47 4.3. Unlinking Blocks 49 4.4. Throttling Blocks 50 4.5. Parallel Processing with Dataflow Blocks 51 4.6. Creating Custom Blocks 52 5. Rx Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 5.1. Converting .NET Events 56 5.2. Sending Notifications to a Context 58 5.3. Grouping Event Data with Windows and Buffers 60 5.4. Taming Event Streams with Throttling and Sampling 62 5.5. Timeouts 64 6. Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 6.1. Unit Testing async Methods 68 6.2. Unit Testing async Methods Expected to Fail 69 6.3. Unit Testing async void Methods 71 6.4. Unit Testing Dataflow Meshes 72 6.5. Unit Testing Rx Observables 74 6.6. Unit Testing Rx Observables with Faked Scheduling 76 7. Interop. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 7.1. Async Wrappers for “Async” Methods with “Completed” Events 81 7.2. Async Wrappers for “Begin/End” methods 83 7.3. Async Wrappers for Anything 84 7.4. Async Wrappers for Parallel Code 86 7.5. Async Wrappers for Rx Observables 87 7.6. Rx Observable Wrappers for async Code 88 7.7. Rx Observables and Dataflow Meshes 90 8. Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 8.1. Immutable Stacks and Queues 96 8.2. Immutable Lists 98 8.3. Immutable Sets 100 8.4. Immutable Dictionaries 102 8.5. Threadsafe Dictionaries 104 8.6. Blocking Queues 106 8.7. Blocking Stacks and Bags 108 8.8. Asynchronous Queues 110 iv | Table of Contents 8.9. Asynchronous Stacks and Bags 113 8.10. Blocking/Asynchronous Queues 115 9. Cancellation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 9.1. Issuing Cancellation Requests 120 9.2. Responding to Cancellation Requests by Polling 123 9.3. Canceling Due to Timeouts 124 9.4. Canceling async Code 125 9.5. Canceling Parallel Code 126 9.6. Canceling Reactive Code 128 9.7. Canceling Dataflow Meshes 130 9.8. Injecting Cancellation Requests 131 9.9. Interop with Other Cancellation Systems 132 10. Functional-Friendly OOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 10.1. Async Interfaces and Inheritance 135 10.2. Async Construction: Factories 137 10.3. Async Construction: The Asynchronous Initialization Pattern 139 10.4. Async Properties 142 10.5. Async Events 145 10.6. Async Disposal 148 11. Synchronization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 11.1. Blocking Locks 158 11.2. Async Locks 160 11.3. Blocking Signals 162 11.4. Async Signals 163 11.5. Throttling 165 12. Scheduling. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 12.1. Scheduling Work to the Thread Pool 167 12.2. Executing Code with a Task Scheduler 169 12.3. Scheduling Parallel Code 171 12.4. Dataflow Synchronization Using Schedulers 172 13. Scenarios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 13.1. Initializing Shared Resources 173 13.2. Rx Deferred Evaluation 175 13.3. Asynchronous Data Binding 176 13.4. Implicit State 178 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Table of Contents | v