I'm testing the below code:
private static void Main()
{
var t = new Thread(() =>
{
var m = new MyCls();
m.DoWork();
});
t.Start();
// simulate time-consuming job
Thread.Sleep(1000);
t.Abort();
Console.Write("\nDone");
}
public class MyCls
{
static MyCls()
{
for (int i = 0; i < 10; i++)
{
Console.Write(i);
Thread.Sleep(1000);
}
}
public void DoWork()
{
Console.WriteLine("executing DoWork..");
}
}
And the output I get is:
0123456789
Done
It seems that t.Abort()
call is blocking the main thread until the execution of the static constructor finishes, and according to the documentation:
The thread that calls
Abort
might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region.
My questions is:
- Do static constructors really run as constrained execution regions (CERs) ?
- If yes, what other code blocks that run as CERs ?
It seems that static constructors are guaranteed to have completed, almost.
Static constructors can be called explicitly with
RuntimeHelpers.RunClassConstructor
which 'Ensures that the type initializer (also known as a static constructor) for the specified type has been run'.In your example, the code could be written as follows.
RunClassConstructor
calls_RunClassConstructor
which is annotated with the following comment.