
The book "Competitiveness and Concurrency on the .NET Platform. Effective Design Patterns ”

If you are writing multithreaded code in .NET, then this book may help you. If you are interested in using a functional paradigm to simplify competitive programming and maximize application performance, this book will be an important guide for you. It will benefit any .NET developer who wants to write competitive, reactive and asynchronous applications that scale and automatically adapt to existing hardware resources wherever such programs work.
Publication structure: roadmap
The fourteen chapters of this book are divided into three parts. Part I presents the functional concepts of competitive programming and describes the skills necessary to understand the functional aspects of writing multithreaded programs.
- Chapter 1 describes the basic concepts and goals of competitive programming, as well as the reasons for using functional programming to write multi-threaded applications.
- Chapter 2 explores a range of functional programming technologies to improve the performance of multi-threaded applications. The purpose of this chapter is to provide the reader with the concepts used in the rest of the book and to introduce powerful ideas that arise from a functional paradigm.
- Chapter 3 gives an overview of the functional concept of immutability. It explains how immutability is used to write predictable and correct competitive programs and to implement functional data structures that are thread safe in nature.
In part II, various models of competitive programming in a functional paradigm are examined in depth. We will explore topics such as the Task Parallel Library (TPL), and implement parallel patterns like Fork / Join, divide and conquer, and MapReduce. This section also discusses declarative layout, high-level abstractions in asynchronous operations, agent programming, and message transfer semantics.
- Chapter 4 outlines the basics of parallel processing of large amounts of data, including templates such as Fork / Join.
- Chapter 5 introduces more sophisticated methods for parallel processing of large amounts of information, such as parallel aggregation, data reduction, and the implementation of a parallel MapReduce template.
- Chapter 6 provides detailed information about the functional methods for processing event (data) streams in real time using the high-order functional operators in .NET Reactive Extensions to form asynchronous event combinators. The studied methods will then be used to implement a competitive publisher-subscriber reactive template.
- Chapter 7 provides an explanation of the task-based programming model as applied to functional programming for implementing competitive operations using the Monadic template. Then this method is used to build a competitive pipeline based on a functional programming paradigm.
- Chapter 8 is devoted to the implementation of unlimited parallel computing using the C # asynchronous programming model. This chapter also discusses error handling methods and methods for constructing asynchronous operations.
- Chapter 9 describes the asynchronous workflow in F #. It shows how a deferred and explicit assessment in this model allows for a higher compositional semantics. Then we will learn how to implement custom computational expressions to raise the level of abstraction to declarative programming.
- Chapter 10 shows how, based on the knowledge gained in previous chapters, combinators and templates, such as Functor, Monad, and Applicative, can be implemented to compose and run several asynchronous operations and handle errors without side effects.
- Chapter 11 analyzes reactive programming using a software messaging model. It reveals the concept of natural isolation as a technology that complements immutability and allows the creation of competitive programs. This chapter focuses on the MailboxProcessor class used in F # to distribute parallel work using agent programming and a resource-free approach.
- Chapter 12 describes agent programming using the TPL Dataflow library from .NET with examples in C #. It shows how to implement stateless and stateful agents in C #, as well as how to perform several calculations in parallel that exchange data with each other, using (sending) messages in the style of a pipeline.
Part III shows how to put into practice all the functional methods of competitive programming studied in previous chapters.
- Chapter 13 presents a set of useful recipes for solving complex competitive problems, taken from real practice. These recipes use all the functional patterns described in this book.
- Chapter 14 describes a full-fledged application developed and implemented using functional competitive templates and methods studied in this book. You will create a highly scalable, responsive server application and a responsive client program. The book contains two versions: one for iOS (iPad), created using Xamarin Visual Studio, and the second - created using Windows Presentation Foundation (WPF). To ensure maximum scalability in the server application, a combination of various programming models, such as asynchronous, agent, and reactive, is used.
The book also contains three applications.
- Appendix A briefly describes the basic concepts of functional programming, as well as presents the basic theory of functional methods used in this book.
- Appendix B reveals the basic concepts of the F # language. This is a basic review of F #, which will allow you to get acquainted with this language and feel comfortable while reading a book.
- Appendix B demonstrates several methods that simplify the interaction between an asynchronous workflow in F # and a .NET task in C #.
Excerpt. 11.6. F # MailboxProcessor: 10,000 agents for Game of Life
Compared to threads, MailboxProcessor in combination with asynchronous workflows is a simple computing unit (primitive). Agents can appear and be destroyed at minimal cost. You can distribute the work among several MailboxProcessor objects in the same way as you can use threads, without the additional overhead associated with creating a new thread. Thanks to this, it is quite possible to create applications consisting of hundreds of thousands of agents working in parallel with a minimum load on computer resources.
In this section, we will use several instances of MailboxProcessor to implement the Game of Life (game "Life") ( wiki-eng and wiki-eng"). According to Wikipedia, the Game of Life, in simple words, is a cellular automaton. This is a game without players — in other words, when a game starts with a random initial configuration, it runs without any other input. The game consists of a set of cells forming a grid; in each cell several mathematical rules are fulfilled. Cells can live, die and multiply. Each cell interacts with eight neighbors (neighboring cells). To move cells in accordance with these rules, it is necessary to constantly calculate the new state of the grid.
Game of Life has the following rules:
- if a cell has only one neighbor or no neighbors, then it dies "from loneliness";
- if four or more neighbors of a cell die, then it dies “due to overpopulation”;
- if the cell has two or three neighbors, then it remains to live;
- if a cell has three neighbors, then it multiplies.
Depending on the initial conditions, the cells form characteristic structures throughout the game. Through repeated application of the rules, the following generations of cells are created until the cells reach a stable state (Fig. 11.12).
Listing 11.9 shows the implementation of the Game of Life AgentCell cell, based on the F # types of MailboxProcessor. Each agent cell interacts with neighboring cells via asynchronous messaging, thus creating a fully parallelized Game of Life. For brevity, I omitted some parts of the code, since they are not related to the main topic of the example. You will find the full implementation in the source code for this book, posted on the publisher’s website.


AgentCell describes a cell in the Game of Life grid. The basic concept is that each agent exchanges information with neighboring cells about its current state through asynchronous messaging. This template creates a chain of interconnected parallel communications that involves all cells sending their updated state to the MailboxProcessor updateAgent. After receiving this data, updateAgent updates the graphics in the user interface (Listing 11.10).


updateAgent, as the name implies, updates the state of each pixel in accordance with the cell value received in the Update message. The agent maintains the state of the pixels and uses it to create a new image when all the cells pass on their new state. UpdateAgent then updates the WPF GUI using this new image that matches the current Game of Life grid:
do! Async.SwitchToContext ctx
image.Source <- createImage pixels
do! Async.SwitchToThreadPool()
It is important to note that the updateAgent uses the current synchronization context to correctly update the WPF controller. The current thread is switched to the user interface thread using the Async.SwitchToContext function (described in Chapter 9).
The last piece of code to execute Game of Life generates a grid that serves as a playground for the cells, and then the timer notifies the cells about the need to perform an update (Listing 11.11). In this example, the grid is a square of 100 × 100 cells, a total of 10,000 cells (MailboxProcessor objects), which are calculated in parallel with a timer every 50 ms, as shown in Fig. 11.13. Ten thousand MailboxProcessor objects interact and update the user interface 20 times per second (the code you should pay attention to is shown in bold).


Notifications to all cells (agents) are sent in parallel using PLINQ. Cells are F # sequences that are treated as .NET IEnumerable, making LINQ / PLINQ easy to integrate.

When the code is executed, the program generates 10,000 F # objects of type MailboxProcessor in less than 1 ms, while the agents occupy less than 25 MB of memory. Impressive!
Summary
- The agent-based programming model naturally provides immutability and isolation when writing competitive systems, making it even easier to discuss complex systems, since agents are encapsulated within active objects.
- A reactive manifest defines the properties for implementing a reactive system that is flexible, loosely coupled, and scalable.
- Natural isolation is important for writing competitive code without blocking. In a multi-threaded program, isolation solves the problem of shared states by providing each thread with a copied piece of data to perform local computations. When using insulation, there is no race condition.
- Being asynchronous, agents are simple because they do not block threads while waiting for messages. As a result, you can use hundreds of thousands of agents in one application without much impact on the amount of memory.
- A MailboxProcessor F # object provides two-way communication: an agent can use an asynchronous channel to return (answer) the result of the calculation to the calling object.
- The agent programming model in F # through MailboxProcessor is an excellent tool for solving bottlenecks in applications, such as multiple concurrent database access. In fact, with the help of agents, you can significantly speed up the application, while maintaining the responsiveness of the server.
- Other .NET programming languages allow you to use the F # type MailboxProcessor, providing methods using the convenient TPL programming model based on tasks.
»More information about the book can be found on the publisher’s website
» Contents
» Excerpt
For Khabrozhiteley 20% discount on the coupon - Concurrency in .NET
Upon payment of the paper version of the book, an electronic version of the book is sent by e-mail.