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);