Saturday, 14 December 2013

Microsoft Bug - In Threading Value pass to each thread is sharing correct value is not receive on thread calling method

Hi In this article we are going to see some critical stuff in Microsoft Dot net Framework, few months back while i am testing a application. I framed a scenario in working , in that scenario i first uses the for each loop to do the work then i thought to change to for loop in C# 5.0 , The funniest thing is when you see logically both the loop are code in the same manner but the result in behavior is different and seems like Bug. so i tried in C# 4.0 version both the For each and For loop are not working in the same scenario. When i say about this to Microsoft they said like the C# compiler is designed like that from the beginning itself. they gave the work around like declare the temp variable to avoid the issue and work in expected manner. but the programmer will always concentrate on the logical thing not the work around things. The Programmer doesn't need to handle the life cycle of thread variable it should be handled by C# compiler Engine.Now let we see the Bug in detailed. 

If the C# 5.0 have a functionality of For each to work correctly then it should work same as For loop, because both are not working in C# 4.0 . so loop must work same for For and ForEach

Click the Link for Bug report details
In Threading Value pass to each thread is sharing

In Threading Value pass to each thread is sharing between the threads so correct value is not receive on thread calling method 


What is happening is we see in this in Example

static Semaphore sem = new Semaphore(3, 3);

                 static void Main(string[] args)
                 {

                         for (int i = 0; i < 11; i++)
                         {
                                 Thread sp= new Thread(() => RunTest(i));
                                 sp.Start();
                         }
                 }

         [MethodImpl(MethodImplOptions.Synchronized)]
         static void RunTest(int f)
                 {
                         try
                         {
                                 Console.WriteLine(f.ToString());
                                 sem.WaitOne();
                                 Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId);
                                 if (f % 2 == 0)
                                 {
                                            Console.WriteLine("7 sec");
                                            Thread.Sleep(7000);
                                 }
                                 else
                                 {
                                            Console.WriteLine(" 14 sec");                                                                 Thread.Sleep(14000);
                                 }
                         }
                         finally
                         {
                                 sem.Release();
                         }
                 }




Now in the above sample i am calling a Method from the thread but the method have a input parameter which is supplied from the for loop so now when a for loop executes each and every time input parameter changes , but when you print value in the called method value is repeating 


Expected output :
0,1,2,3,4,5,6,7,8,9,10

Actual Output:
0,1,2,2,2,5,6,6,6,8,10

So how to avoid this problem from Microsoft side there are saying that this C# compiler is designed like that so developers has to declare a temp variable to hold the value like below sample to avoid the error.


static Semaphore sem = new Semaphore(3, 3);

                 static void Main(string[] args)
                 {

                         for (int i = 0; i < 11; i++)
                         {
                                 int x=i; // New statement declared
                                 Thread sp= new Thread(() => RunTest(x));
                                 sp.Start();
                         }
                 }

         [MethodImpl(MethodImplOptions.Synchronized)]
         static void RunTest(int f)
                 {
                         try
                         {
                                 Console.WriteLine(f.ToString());
                                 sem.WaitOne();
                                 Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId);
                                 if (f % 2 == 0)
                                 {
                                            Console.WriteLine("7 sec");
                                            Thread.Sleep(7000);
                                 }
                                 else
                                 {
                                            Console.WriteLine(" 14 sec");                                                                 Thread.Sleep(14000);
                                 }
                         }
                         finally
                         {
                                 sem.Release();
                         }
                 }

Now in this one question if the C# compiler is behave like this , developers has to kept in mind that they have  to declare the temp variable while code the thread , that is not a rule specified in any OOPS concepts even there is no problem like this in Java Thread sharing a variable. But Microsoft changes the Foreach behavior in the C# 5.0 but have issue in C# 4.0 if they stated that is not a issue then why they change the Behavior of foreach in newer version below sample have issue in C# 4.0 but works  correctly in C# 5.0

In Foreach Loop

 void call(string[] args)
        {
            var runningnumbers = Enumerable.Range(1, 10);
            List<Action> procaction = new List<Action>();
            foreach (var item in runningnumbers)
            {
                Action lambda = () =>
                {
                    var result = 2 +10 + item;
                    Console.WriteLine(result);
                };
                procaction.Add(lambda);
            }

            foreach (var work in procaction)
            {
                work();
            }
            Console.Read();
        }




Solution

Expected output :
13
14
15
16
17
18
19
20
21
22

Actual Output:
22
22
22
22
22
22
22
22
22
22

but this problem is solved in C# 5.0 in ForEach loop,


From this article you can learn some of the basic things in C# and how to get the required output while developing from the global oops concepts.


No comments:

Post a Comment