The static constructor will finish running before any thread is allowed to access the class.
private class InitializerTest
{
static private int _x;
static public string Status()
{
return "_x = " + _x;
}
static InitializerTest()
{
System.Diagnostics.Debug.WriteLine("InitializerTest() starting.");
_x = 1;
Thread.Sleep(3000);
_x = 2;
System.Diagnostics.Debug.WriteLine("InitializerTest() finished.");
}
}
private void ClassInitializerInThread()
{
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() starting.");
string status = InitializerTest.Status();
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() status = " + status);
}
private void classInitializerButton_Click(object sender, EventArgs e)
{
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
}
The code above produced the results below.
10: ClassInitializerInThread() starting.
11: ClassInitializerInThread() starting.
12: ClassInitializerInThread() starting.
InitializerTest() starting.
InitializerTest() finished.
11: ClassInitializerInThread() status = _x = 2
The thread 0x2650 has exited with code 0 (0x0).
10: ClassInitializerInThread() status = _x = 2
The thread 0x1f50 has exited with code 0 (0x0).
12: ClassInitializerInThread() status = _x = 2
The thread 0x73c has exited with code 0 (0x0).
Even though the static constructor took a long time to run, the other threads stopped and waited. All threads read the value of _x set at the bottom of the static constructor.
Instanceat once. One of the threads will be told to first run the type initializer (also known as the static constructor). Meanwhile all other threads wanting to read theInstanceproperty, will be locked until the type initializer has finished. Only after the field initializer has concluded, will threads be allowed to get theInstancevalue. So no-one can seeInstancebeingnull.Xends up being-1even without threading. It is not a thread-safety issue. Instead, the initializerx = -1runs first (it is on an earlier line in the code, a lower line number). Then the initializerX = GetX()runs, which makes upper-caseXequal to-1. And then the "explicit" static constructor, the type initializerstatic C() { ... }runs, which changes only lower-casex. So after all that, theMainmethod (orOthermethod) can go on and read upper-caseX. Its value will be-1, even with just one thread.