wicker0020_8_m1.jpg

How to properly use multi threading

Programmers who start coding with multi threading and C#, get different first impressions.

First, they are either afraid of new frameworks and patterns, then try their own methods. Secondly, they are brave, ready to jump on Visual Studio, C# and start learning multi threading. I had to be brave, I didn't have the luxury to wait, so I jumped right in to face the problems and adventures head on. Don't go out there learning everything about Multi threading right away, your head might hurt, start slow and as you get stuck, look things up and you'll learn faster.  My first experience with threads came at a shock, my variables started changing on their own. I was like why is this happening!? Later I discovered that using static keyword is a good and bad thing when using threads. One, static is great if you need to share something among the threads, but just don't forget that you're sharing. Two, Static methods in particular aren't thread safe. To ensure thread safety, you should consider Locking, only allow one thread at a time. Shared variables can keep you up at night because its hard to catch which thread is changing its value and can cause your application to produce the wrong result. Moreover, when writing a multi threaded application, watch out for Race Conditions, they occur when two or more threads try to change a variable, whoever gets their first will change it. Please, for your sake, just use locking, to prevent a variable from wrongly changing, until you find a clever way to prevent leaks. Okay, so what if a variable changes? Development How will it affect me? Well, I had a situation, that goes something like this: say for example, I have box A and box B, both of which need to be saved to the database, and box A will get a SSN# and box B will have a date. Now imagine I have a loop that runs for a long time and does some logic and manipulation before it gets to box A and B. box A and B are both static, we are using Multi threading technique within the TPL, we start changing A and B boxes, meanwhile other thread caught up and changed A to the new SSN#, so now we have both threads with the same SSN# being saved to the database. Now if we added a lock inside the method to wait, till both box A and B finished saving, we would have prevented the above scenario. Development Fine this is great, why hasn't anyone figured out a better way, than using primitive locking. Well, you're in luck, if your swing over to the MSDN System.Collections.Concurrent, they have some great data structures that take care of the locking for you and speed up development. I strongly recommend spending some time with Concurrent Queues. I started with them first.

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

class CQ_EnqueueDequeuePeek
{
   // Demonstrates: 
   // ConcurrentQueue.Enqueue() 
   // ConcurrentQueue.TryPeek() 
   // ConcurrentQueue.TryDequeue() 
   static void Main ()
   {
      // Construct a ConcurrentQueue.
      ConcurrentQueue cq = new ConcurrentQueue();

      // Populate the queue. 
      for (int i = 0; i < 10000; i++) cq.Enqueue(i);

      // Peek at the first element. 
      int result;
      if (!cq.TryPeek(out result))
      {
         Console.WriteLine("CQ: TryPeek failed when it should have succeeded");
      }
      else if (result != 0)
      {
         Console.WriteLine("CQ: Expected TryPeek result of 0, got {0}", result);
      }

      int outerSum = 0;
      // An action to consume the ConcurrentQueue.
      Action action = () =>
      {                
         int localSum = 0;
         int localValue;
         while (cq.TryDequeue(out localValue)) localSum += localValue;
         Interlocked.Add(ref outerSum, localSum);
      };

      // Start 4 concurrent consuming actions.
      Parallel.Invoke(action, action, action, action);

      Console.WriteLine("outerSum = {0}, should be 49995000", outerSum);
   }
}

 

 

Leave A Comment