3

I was trying to add threading to a static class that I have and came across a bunch of problems. I read this thread and the blog post that it links to and I think I understand what's going on. But I can't figure out why the Parallel For loop still works as in this example:

using System;
using System.Threading;
using System.Threading.Tasks; 

namespace ThreadingTest
{
    public static class TestClass
    {
        public static int AwesomeNum = 43; 

        static TestClass()
        {
            string[] x = { "deal", "witch", "panda"};

            //does not cause a deadlock? huh?
            Parallel.For(0, x.Length,  i =>
                {
                    Console.WriteLine(x[i]); 
                });

            //results in a deadlock
            //Parallel.Invoke(writesomething, writesomethingelse); 

            //results in deadlock
            Thread thread = new Thread(new ThreadStart(() =>
            {
                Console.WriteLine("there is a bear in my soup"); 
            }));

            thread.Start();
            thread.Join(); 
        }

        private static void writesomething()
        {
            Console.WriteLine("writing something"); 
        }

        private static void writesomethingelse()
        {
            Console.WriteLine("writing something else."); 
        }
    }
}


using System;

namespace ThreadingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(TestClass.AwesomeNum.ToString()); 
        }
    }
}
Community
  • 1
  • 1
Cuthbert
  • 2,908
  • 5
  • 33
  • 60
  • 1
    You might be interested in my recent series of articles about static constructor semantics. http://ericlippert.com/2013/02/06/static-constructors-part-one/ – Eric Lippert Apr 02 '13 at 21:43

1 Answers1

7

The following does cause a deadlock:

Parallel.For(0, x.Length,  i => {
   Console.WriteLine(i); 
});

What's the difference?

The lambda expression I wrote above gets compiled as a method inside TestClass. So does the one you wrote in your new Thread example.

The lambda you wrote in the parallel expression, i => Console.WriteLine(x[i]), is compiled into a different, compiler-generated class because it captures x. So to execute it needs to statically initialize the closure class, but not TestClass.

So it's nothing to do with Parallel vs any other threading mechanism. It's just the difference between a lambda which requires the generation of a closure object and one which does not.

Note, I am describing the behavior of the current compiler. This behavior may be found in the relevant specifications, or it could be implementation-defined. I haven't looked.

Jacob
  • 1,699
  • 10
  • 11
  • 2
    The details of how closure classes are realized is called out as an implementation detail in the C# specification. – Eric Lippert Apr 02 '13 at 21:41