C # concurrent set of sets,

Source: Internet
Author: User

C # concurrent set of sets,

Starting from. NET 4, several thread-safe Collection classes are provided in System. Collection. Concurrent. A thread-safe set prevents multiple threads from accessing the set in conflict mode.
The IProducerConsumerCollection interface is defined for thread-safe access to the collection. The most important methods in this interface are TryAdd () and TryTake (). The TryAdd () method tries to add an item to the set. However, if the set does not allow adding an item, this operation may fail. The TryAdd () method returns a Boolean value, indicating whether the operation is successful or failed. TryTake () returns the items in the set when the call succeeds.
* ConcurrentQueue <T> ---- this collection class is implemented using a locking-free algorithm, which is internally merged into a 32-item array in a linked list. This class includes the Enqueue (), TryDequeue (), and TryPeek () methods. Because this class implements the IProducerConsumerCollection <T> interface, the TryAdd () and TryTake () methods only call the Enqueue and TryDequeue methods.
* ConcurrentStack <T> ---- similar to ConcurrentQueue <T>. This class defines the Push (), PushRange (), TryPeek (), TryPop (), and TryPopRange () methods. This class uses the linked list of its elements internally.
* ConcurrentBag <T> ---- this class does not define any order for adding or extracting items. This class uses the concept of a thread ing to an array used internally, so it tries to reduce the lock. Method: Add (), TryPeek (), TryTake ().
* ConcurrentDictionary <TKey, TValue> ---- This is a set of thread-safe key values. The TryAdd (), TryGetValue (), TryRemove (), and TryUpdate () Methods access members in a non-blocking manner. Because the elements are based on keys and values, the ConcurrentDictionary <TKey, TValue> API IProducerConsumerCollection <T> is not implemented.
* BlockingCollection <T> ---- this collection blocks threads and waits until elements can be added or extracted. The BlockingCollection <T> set provides an interface to delete and Add elements using the Add () and Take () methods. These methods will block the thread. The Add () method has an overloaded version, which can pass a CancellationToken to this overloaded version. This token allows you to cancel blocked calls. If you do not want to wait infinitely and do not want to cancel calling from the outside, you can use the TryAdd () and TryTake () methods. In these methods, you can also specify a timeout value.
BlockingCollection <T> is a modifier for any class that implements the IProducerConsumerCollection <T> interface. It uses the ConcurrentQueue <T> class by default. You can also pass to the constructor any class that implements the IProducerConsumerCollection <T> interface.

The following example shows how to use BlockingCollection <T>. One task writes data to one set and the other task reads data from the set.

Static void Main (string [] args) {StartPipeline (); Console. readLine ();} private static async void StartPipeline () {// storage file name var fileNames = new BlockingCollection <string> (); // store the content of each row of the file var lines = new BlockingCollection <string> (); // store each word in each row. The word is a key, the number of words is the value var words = new ConcurrentDictionary <string, int> (); // store the words information var items = new BlockingCollection <Info> (); var coloredItems = new BlockingCo Llection <Info> (); Task t1 = PipelineStages. readFilenamesAsync (@".. /.. /.. ", fileNames); ConsoleHelper. writeLine ("started stage 1"); Task t2 = PipelineStages. loadContentAsync (fileNames, lines); ConsoleHelper. writeLine ("started stage 2"); Task t3 = PipelineStages. processContentAsync (lines, words); await Task. whenAll (t1, t2, t3); ConsoleHelper. writeLine ("stages 1, 2, 3 completed"); // when the preceding three tasks are completed, the following Task t4 = PipelineStages. transferContentAsync (words, items); Task t5 = PipelineStages. addColorAsync (items, coloredItems); Task t6 = PipelineStages. showContentAsync (coloredItems); ConsoleHelper. writeLine ("stages 4, 5, 6 started"); await Task. whenAll (t4, t5, t6); ConsoleHelper. writeLine ("all stages finished");} public static class PipelineStages {public static Task ReadFilenamesAsync (string pat H, BlockingCollection <string> output) {return Task. run () => {foreach (string filename in Directory. enumerateFiles (path ,"*. cs ", SearchOption. allDirectories) {output. add (filename); ConsoleHelper. writeLine (string. format ("stage 1: added {0}", filename);} // call CompleteAdding, notify all readers that they should not wait for any additional items in the set. // if this method is not called, the reader waits for more items to be added in the foreach loop. completeAdding () ;});} public static async Task LoadCont EntAsync (BlockingCollection <string> input, BlockingCollection <string> output) {// when using a reader to read a collection, you must use GetConsumingEnumerable to obtain the enumerator that blocks the collection, // If you directly use input to iterate the set, this will only iterate the set in the current state, and will not iterate the items added after the foreach (var filename in input. getConsumingEnumerable () {using (FileStream stream = File. openRead (filename) {var reader = new StreamReader (stream); string line = null; while (line = await reader. readLineAsync ())! = Null) {output. add (line); ConsoleHelper. writeLine (string. format ("stage 2: added {0}", line) ;}} output. completeAdding ();} public static Task ProcessContentAsync (BlockingCollection <string> input, ConcurrentDictionary <string, int> output) {return Task. run () => {foreach (var line in input. getConsumingEnumerable () {string [] words = line. split ('', ';', '\ t ','{','}','(',')',':',',','" '); Foreach (var word in words. Where (w =>! String. isNullOrEmpty (w) {// an extension method of the dictionary output is used here. addOrIncrementValue (word); ConsoleHelper. writeLine (string. format ("stage 3: added {0}", word) ;}});} public static Task TransferContentAsync (ConcurrentDictionary <string, int> input, blockingCollection <Info> output) {return Task. run () => {foreach (var word in input. keys) {int value; if (input. tryGetValue (word, out value) {var info = new I Nfo {Word = word, Count = value}; output. add (info); ConsoleHelper. writeLine (string. format ("stage 4: added {0}", info) ;}} output. completeAdding () ;});} public static Task AddColorAsync (BlockingCollection <Info> input, BlockingCollection <Info> output) {return Task. run () => {foreach (var item in input. getConsumingEnumerable () {if (item. count> 40) {item. color = "Red";} else if (item. count> 20) {item. color = "Yellow";} else {item. color = "Green";} output. add (item); ConsoleHelper. writeLine (string. format ("stage 5: added color {1} to {0}", item, item. color);} output. completeAdding () ;});} public static Task ShowContentAsync (BlockingCollection <Info> input) {return Task. run () => {foreach (var item in input. getConsumingEnumerable () {ConsoleHelper. writeLine (string. format ("sta Ge 6: {0} ", item), item. color) ;}}}}// create a dictionary Extension Method public static class ConcurrentDictionaryExtension {public static void AddOrIncrementValue (this ConcurrentDictionary <string, int> dict, string key) {bool success = false; while (! Success) {int value; if (dict. tryGetValue (key, out value) {if (dict. tryUpdate (key, value + 1, value) {success = true ;}} else {if (dict. tryAdd (key, 1) {success = true ;}}}}}

 

Here we use a pipeline model programming mode, the content added above, the content processed below

Related Article

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.