none
static constructor hangs RRS feed

  • Question

  • I am seeing a hang in a static constructor of a class I had implemented. This class creates a form in the static constructor and blocks until the form is loaded. Here's what my code looks like:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;

    namespace ConsoleApplication2
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                MyClass instance = new MyClass();
            }
        }

        public class MyClass
        {
            private static ManualResetEvent waitHandle;
           
            static MyClass()
            {
                waitHandle = new ManualResetEvent(false);
                Thread uiThread = new Thread(() =>
                {
                    Form form = new Form();
                    form.Load += (s, e) =>
                    {
                        waitHandle.Set();
                    };
                    Application.Run(form);
                });
                uiThread.SetApartmentState(ApartmentState.STA);
                uiThread.Start();

                waitHandle.WaitOne();
                MessageBox.Show("waitOne returned");
                waitHandle.Close();
                waitHandle = null;
            }

            public MyClass()
            {

            }

        }
    }

    The UI thread never starts and the code hangs. Now if I move the call to waitOne() to MyClass constructor as follows, everything works as expected. Does anyone know why?

     using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;

    namespace ConsoleApplication2
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                MyClass instance = new MyClass();
            }
        }

        public class MyClass
        {
            private static ManualResetEvent waitHandle;
           
            static MyClass()
            {
                waitHandle = new ManualResetEvent(false);
                Thread uiThread = new Thread(() =>
                {
                    Form form = new Form();
                    form.Load += (s, e) =>
                    {
                        waitHandle.Set();
                    };
                    Application.Run(form);
                });
                uiThread.SetApartmentState(ApartmentState.STA);
                uiThread.Start();


            }

            public MyClass()
            {
                waitHandle.WaitOne();
                MessageBox.Show("waitOne returned");
                waitHandle.Close();
                waitHandle = null;
            }

        }
    }


     

    Monday, March 22, 2010 11:42 PM

Answers

  • Your MyClass static constructor waits on uiThread to set waiHandle event. That happens in the new thread code which has to run static constructor of MyClass first, because it touches its waitHandle static field in Form.Load delegate, ... therefore it deadlocks.
    MyClass static constructor holds a MyClass-static-contructor-lock until it finishes. Another thread (uiThread in your case) therefore cannot access its static fields, until it finishes.

    -Karel

    • Marked as answer by SamAgain Monday, March 29, 2010 4:08 AM
    Tuesday, March 23, 2010 12:48 AM
    Moderator