C# 静态构造函数是否作为CER运行?

C# 静态构造函数是否作为CER运行?,c#,clr,threadabortexception,thread-abort,cer,C#,Clr,Threadabortexception,Thread Abort,Cer,我正在测试以下代码: 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.Writ

我正在测试以下代码:

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..");
    }
}
看来,
t.Abort()
调用正在阻塞主线程,直到静态构造函数的执行完成,并且根据:

如果要中止的线程位于受保护的代码区域(如catch块、finally块或受约束的执行区域),则调用
中止的线程可能会阻塞

我的问题是:

  • 静态构造函数真的作为受约束的执行区域(CER)运行吗
  • 如果是,还有哪些代码块作为CER运行
  • 更新:问题是关于
    t.Abort()
    blocking,而不是interrupting,所以这个答案几乎不相关:)


    的文档明确指出中止可以中止静态构造函数

    当线程对自身调用Abort时,其效果类似于抛出异常;ThreadAbortException立即发生,结果是可预测的。但是,如果一个线程在另一个线程上调用Abort,Abort会中断正在运行的任何代码。静态构造函数也有可能被中止。在极少数情况下,这可能会阻止在该应用程序域中创建该类的实例

    例如,调用Thread.Abort可能会阻止静态构造函数执行或阻止非托管资源的释放


    虽然您的示例优雅地显示了静态构造函数可能不会被中断,但无法保证这种行为


    更新 下面是一个静态ctor被Abort()中断的示例

    代码
    看起来静态构造函数几乎已经完成了

    可以显式调用静态构造函数,其中“确保指定类型的类型初始值设定项(也称为静态构造函数)已运行”

    在您的示例中,代码可以编写如下

    var t = new Thread(() =>
    {
      System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(MyCls).TypeHandle);
      var m = new MyCls();
    });
    
    
    RunClassConstructor
    调用,该调用带有以下注释

    在没有类构造函数死锁条件的情况下,进一步保证调用已完成


    请注意
    Thread.Abort()
    可能会损坏运行时。调用abort的唯一安全时间是当您试图完全从应用程序中崩溃时,即中止所有线程。@Enigmativity是的,我知道
    Thread.abort()
    是一种不好的做法,我只是试图了解CLR在某些情况下的行为。我的示例不仅仅表明静态构造函数可能不会被中断,它还显示调用线程被阻塞,并且
    thread.Abort()
    阻塞调用线程的情况很可能(仅?)发生在受保护的代码区域中。明白了吗。您更关心的是阻塞,而不是中止。
    public static void Main()
    {
        Console.WriteLine($"START");
        var t = new Thread(() =>
        {
            var m = new MyCls();
        });
        Console.WriteLine($"t.Start");
        t.Start();
    
        Thread.Sleep(2000);
        Console.WriteLine($"Trying to create a new object");
    
        try
        {
            var m2 = new MyCls();
    
        }
        catch (Exception ex) { Console.WriteLine(ex); }
        Console.WriteLine("All done");
        Console.ReadLine();
    }
    
    
    public class MyCls
    {
        static MyCls()
        {
            for (int i = 0; i < 10; i++)
            {
                if (i == 4)
                {
                    Console.WriteLine($"sctor calling Abort on itself");
                    Thread.CurrentThread.Abort();
                };
                Console.WriteLine($"sctor.{i}");
                Thread.Sleep(100);
            }
        }
    }
    
    START
    t.Start
    sctor.0
    sctor.1
    sctor.2
    sctor.3
    sctor calling Abort on itself
    Trying to create a new object
    System.TypeInitializationException: The type initializer for 'MyCls' threw an exception. ---> System.Threading.ThreadAbortException: Thread was being aborted.
       at System.Threading.Thread.AbortInternal()
       at System.Threading.Thread.Abort()
       at Program.MyCls..cctor() in c:\users\letss\source\repos\ConsoleApp2\ConsoleApp2\Program.cs:line 42
       --- End of inner exception stack trace ---
       at Program.MyCls..ctor()
       at Program.Main() in c:\users\letss\source\repos\ConsoleApp2\ConsoleApp2\Program.cs:line 21
    All done
    
    var t = new Thread(() =>
    {
      System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(MyCls).TypeHandle);
      var m = new MyCls();
    });
    
    
    // RunClassConstructor causes the class constructor for the given type to be triggered
    // in the current domain.  After this call returns, the class constructor is guaranteed to
    // have at least been started by some thread.  In the absence of class constructor
    // deadlock conditions, the call is further guaranteed to have completed.
    //
    // This call will generate an exception if the specified class constructor threw an 
    // exception when it ran. 
    [System.Security.SecuritySafeCritical]
    [ResourceExposure(ResourceScope.None)]
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private static extern void _RunClassConstructor(RuntimeType type);