C # Concurrent Programming Classic Example notes

Source: Internet
Author: User

    • 1. Preface
    • 2. At the outset
    • 3. Development principles and key points
      • (1) Concurrent Programming Overview
      • (2) Asynchronous Programming Basics
      • (3) The basis of parallel development
      • (4) Test techniques
      • (5) Collection
      • (6) Functional OOP
      • (7) Synchronization
1. Preface

Recently took advantage of a steady period of the project to study a lot of books, including the "C # concurrent Programming Classic example" to my impression is still relatively profound. Of course, this may be due to the recent period of the book most of the mouth cannon more than the actual, such as "Head First design mode" "Cracking The coding interview" and so on, so suddenly see a "example" under the banner of the book, or quite let me feel refreshing. For the purpose of sharing and deepening understanding, I have specially compiled some notes (mainly the content that is easy to be involved in web development, so some chapters such as Data flow, RX, etc. I have looked and skipped directly) for review study. The charm of language and technology is really unpredictable.

2. At the outset

There has always been a view that the implementation of the underlying architecture, writing drivers and engines, or the framework and tool development is the senior developers, do the upper-level application is only "code farmers", in fact, can take advantage of the platform provided by the relevant library, rather than all using the underlying technology to achieve their own, to develop high-quality, stable applications, The test of technical ability is not less than the development of the underlying library, such as tpl,async,await.

3. Development principles and key points (1) Concurrent Programming Overview
  1. Concurrency: Multitasking at the same time
  2. Multithreading: A form of concurrency that uses multiple threads to execute a program
  3. Parallel processing: Splitting a large number of tasks in progress into small chunks, allocated to multiple concurrently running threads
  4. Parallel processing is a kind of multithreading, and multithreading is a processing form of concurrency.
  5. Asynchronous programming: A form of concurrency that uses the future mode or callback mechanism to avoid unnecessary threading
  6. The core idea of asynchronous programming is asynchronous operations: the operations that are initiated are completed over a period of time. When this operation is executing, the original thread is not blocked. The thread that initiated the operation can continue to perform other tasks. When the operation is complete, the future is notified, or a callback function is called to let the program know that the operation has ended
  7. The purpose of the await keyword is to start a task that will be executed (the task will run in a new thread) and return immediately so that the function in which the await is located is not blocked. After the task completes, continue with the code behind the await
  8. Responsive programming: A declarative-based programming approach to concurrency in which programs react to events in this mode
  9. Do not use void as the return type of the Async Method! The Async method can return void, but this is limited to writing event handlers. A normal async method, if there is no return value, to return a Task instead of void
  10. The Async method executes synchronously at the beginning. Inside the Async method, the await keyword performs an asynchronous wait on its parameters. It first checks whether the operation has completed and, if it is done, continues to run (synchronous mode). Otherwise, it pauses the Async method and returns, leaving an unfinished task. After some time, the operation is completed and the Async method resumes running.
  11. After an exception is thrown in the await code, the exception progresses along the task direction to the reference
  12. Once you have used async in your code, it's best to always use it. When you call an async method, you should (at the end of the call) wait for the task object it returns with await. Be sure to avoid using the task.wait or Task.result methods, as they can cause deadlocks
  13. A thread is a separate running unit with multiple threads inside each process, each of which can execute instructions concurrently. Each thread has its own stand-alone stack, but shares memory with other threads in the process
  14. Each. NET application maintains a thread pool, in which case the application will hardly need to create a new thread on its own. If you want to create the SAT thread for a COM interop program, you have to create the thread, which is the only case where the thread is required
  15. Threads are low-level abstractions, and thread pools are slightly more advanced abstractions
  16. There are two types of collections used in concurrent programming: Concurrency becomes + immutable collection
  17. Most concurrent programming techniques have a similar point: they are essentially functional. The function here is as a programming pattern based on the combination of functions. One programming principle of a function is brevity (avoidance of side effects), and the other is invariance (meaning that a piece of data cannot be modified)
  18. . NET 4.0 introduces a parallel task library (TPL) that fully supports data parallelism and task parallelism. However, some platforms with fewer resources, such as mobile phones, typically do not support TPL. TPL is a. NET framework that comes with
(2) Asynchronous Programming Basics
    1. An exponential backoff is a retry policy that increases the delay time for retries. The best way to access a WEB service is to use exponential backoff, which can prevent the server from being blocked by too many retries
StaticAsync task<String>Downloadstringwithretries (string URI) {using (var client = new HttpClient ()) {//1th retry wait 1 seconds, 2nd time etc 2 seconds, 3rd time and so on 4 seconds. var nextdelay = timespan.fromseconds (1); for (int i = 0; I! = 3; ++i) {try {return await client. Getstringasync (URI); } catch {} await task.delay (nextdelay); nextDelay = NextDelay + Nextdelay; } //last retry, so that the caller knows the error message. return await client. Getstringasync (URI); }}  
    1. The task.delay is suitable for unit testing of asynchronous code or for implementing retry logic. To implement the timeout function, it is best to use CancellationToken
    2. How to implement a synchronous method that has an asynchronous signature. This can happen if you inherit code from an asynchronous interface or base class, but you want to implement it in a synchronous way. The workaround is to use the Task.fromresult method to create and return a new Task object, which is completed and has the specified value
    3. Use the IProgress and Progress types. The Async method you write needs to have the IProgress parameter, where T is the type of progress that needs to be reported and can show the progress of the operation
    4. Task.whenall can wait for all tasks to complete and optionally catch exceptions when each task throws an exception
    5. Task.whenany can wait for either task to complete, although it can complete the time-out task (where one task is set to Task.delay), but obviously it is better to handle it with a special cancellation token timeout function
    6. The first chapter refers to the problem of async and context: By default, an async method runs in its original context when it resumes running after an await call. When the extension method Configureawait (false) is added, the context is discarded after the await
(3) The basis of parallel development
    1. The Parallel class has a simple member invoke that can be used to call a batch of methods in parallel, and these methods (most of them) are independent of each other
StaticvoidProcessarray (double[] array) { Parallel.Invoke (() = Processpartialarray (array, 0, array. Length/2), () = Processpartialarray (array, array. Length/2,array. Length));} static void processpartialarray (double[] Span class= "hljs-built_in" >array, int begin, int end) {//computationally intensive process ...}            
    1. In concurrent programming, the task class has two functions: as a parallel task, or as an asynchronous task. Parallel tasks can use blocking member functions, such as task.wait, Task.result, Task.waitall, and Task.waitany. Parallel tasks often also use attachedtoparent to establish a "parent/child" relationship between tasks. Parallel tasks need to be created with Task.run or Task.Factory.StartNew.
    2. Instead, asynchronous tasks should avoid blocking member functions, instead using await, task.whenall, and task. WhenAny. Asynchronous tasks do not use attachedtoparent, but you can create an implicit "parent/child" relationship by being able to await another task.
(4) Test techniques
    1. MSTest unit tests that support async Task types starting from the visual Studio2012 version
    2. If the unit test framework does not support unit tests of the async Task type, you will need to make some additional modifications to wait for the asynchronous operation. One of these practices is to use task.wait and to disassemble the AggregateException object when there is an error. My advice is to use the Asynccontext class in NuGet package Nito.asyncex

Attached here is an operational Asynchelper class implemented in the ABP, which is based on the Asynccontext implementation

    ///<summary>Provides some helper methods to work with async methods.///</summary>PublicStaticClassAsynchelper {///<summary>Checks If given method is an async method.///</summary>///<param name= "Method" >a method to check</param>PublicStaticboolIsasyncmethod (MethodInfo method) {Return (method. ReturnType = =typeof (Task) | | (method. Returntype.isgenerictype && method. Returntype.getgenerictypedefinition () = =typeof (Task<>)); }///<summary>Runs a async method synchronously.///</summary>///<param name= "func" >a function that returns A result</param>///<typeparam name= "TResult" >result type</typeparam>///<returns>result of the async operation</returns>PublicStatic TResult runsync<tresult> (func<task<tresult>> Func) {return Asynccontext.run (func);} ///<summary> ///Runs a async method synchronously. ///</summary> ///<param name=" action ">An async action< Span class= "Hljs-doctag" ></param> public static void runsync ( func<task> Action) {Asynccontext.run (action);} } 
    1. One of the key criteria in async code is to avoid using async void. I highly recommend that you do code refactoring when you do unit tests on the async void method, rather than using Asynccontext.
(5) Collection
    1. A thread-safe collection is a mutable collection that can be modified simultaneously by multiple threads. Thread-safe collections are blended with fine-grained locking and lock-free techniques to ensure that threads are blocked for the shortest time possible (typically without blocking at all). When enumerating through many thread-safe collections, a snapshot of the collection (snapshot) is created internally, and the snapshot is enumerated. The main advantage of a thread-safe collection is that multiple threads can safely access it, and the code will only be blocked for a very short time, or not block at all

    2. Concurrentdictionary<tkey, tvalue= "" > is a boutique in data structures that is thread-safe, mixed with fine-grained locking and lock-free technology to ensure fast access in most cases.

    3. Concurrentdictionary<tkey, tvalue= "" > Built-in AddOrUpdate, Tryremove, TryGetValue and other methods. If multiple threads read and write a shared collection, using Concurrentdictionary<tkey, tvalue= "" > is the most appropriate, and if not frequently modified, it is more appropriate to use Immutabledictionary<tkey, Tvalue= "" >. And if some threads only add elements, some threads only remove elements, preferably using a producer/consumer collection

(6) Functional OOP
    1. Asynchronous programming is functional (functional), and. NET-introduced async allows developers to think programmatically when programming asynchronously, but in internal implementations, asynchronous programming is still functional

      The great man has said that the world is both procedural and functional, but ultimately functional

    2. Can wait for a class (such as a task object) with await, rather than a method. You can wait for a method to return a task with an await, whether it is an async method or not. The constructor for the

    3. Class is not asynchronous, and you can generally use the following methods. Accordingly, we can pass var instance=new program.createasync ();

  class program {private program () {} private async task< program> Initializeasync () {await Task.Delay ( Timespan.fromseconds (1)); return this;} public static Task<Program > Createasync () {var result = new program (); return result. Initializeasync (); } } 
    1. When writing an asynchronous event handler, the event argument class is preferably thread-safe. The simplest way to do this is to make it immutable (that is, all properties are set to read-only)
(7) Synchronization
    1. There are two main types of synchronization: Communication and Data protection

    2. Synchronization is required to protect shared data if all three of the following conditions are met
    • Multi-segment code is running concurrently
    • These pieces of code are accessing (reading or writing) the same data
    • At least one piece of code is modifying (writing) the data
    1. Observe the following code to determine its synchronization and operational status
Classshareddata{Publicint Value {GetSet }}Async TaskModifyvalueasync (shareddata data) {await task.delay (timespan.fromseconds (1;} //Warning: Synchronization may be required, see the discussion below. async task<int> modifyvalueconcurrentlyasync (var data = new shareddata (); //initiates three concurrent modification processes. var Task1 = modifyvalueasync (data); var task2 = modifyvalueasync (data); var task3 = modifyvalueasync (data); await task.whenall (Task1, Task2, TASK3); return data. Value;}                 

In this example, three concurrent run modification processes are initiated. Do you need to synchronize? The answer is "look at the situation". If you can be sure that this method is called in a GUI or ASP. NET context (or any other context that allows only one piece of code to run at the same time), then no synchronization is required, because the three modified data processes run at different times. For example, if it runs in the GUI context, there is only one UI thread that can run the data modification process, so only one procedure will run for a period of time. Therefore, it is not necessary to synchronize if you can determine the context in which a piece of code runs at the same time. However, if you call this method from a thread-pool, such as task.run, you need to synchronize. In that case, the three data modification processes run on separate thread pool threads and modify data at the same time. Value, so you must have access to data synchronously. Value.

    1. Immutable types are thread-safe in themselves, and it is not possible to modify an immutable collection, even if multiple task.run are used to add data to the collection, and no synchronous operation is required

    2. A thread-safe collection (for example, concurrentdictionary) is completely different. Unlike immutable collections, a thread-safe collection can be modified. The thread-safe collection itself contains all the synchronization capabilities

    3. There are four important guidelines for the use of locks
    • Limit the scope of a lock (for example, to set the object used by the lock statement to be a private member)
    • What is the purpose of writing a lock in a document
    • Minimal code within the lock range (do not block when locked)
    • Never run arbitrary code when controlling locks (do not invoke event handling in statements, call virtual methods, invoke delegates)
    1. If you need an asynchronous lock, try Semaphoreslim

    2. Do not in ASP. NET, which is because in ASP. Task.run, the code that processes the request is run in the thread pool threads, and forcing it to another thread pool is often counterproductive

(7) Practical tips

    1. A resource is shared by multiple parts of the program and is now initialized when the resource is accessed for the first time.
static int _simpleValue;static readonly Lazy<Task<int>> MySharedAsyncInteger = new Lazy<Task<int>>(() => Task.Run(async () => { await Task.Delay(TimeSpan.FromSeconds(2)); return _simpleValue++; }));async Task GetSharedIntegerAsync(){ int sharedValue = await MySharedAsyncInteger.Value;}

C # Concurrent Programming Classic Instance notes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.