静态构造函数 运行 是否作为 CER?
Do static constructors run as CERs?
我正在测试以下代码:
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..");
}
}
我得到的输出是:
0123456789
Done
似乎 t.Abort()
调用阻塞了主线程,直到静态构造函数的执行完成,并且根据 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.
我的问题是:
- 静态构造函数真的 运行 作为受限执行区域 (CER) 吗?
- 如果是,还有哪些其他代码阻止 运行 作为 CER?
更新:问题是关于 t.Abort()
阻塞,而不是中断,所以这个答案几乎不相关:)
Thread.Abort Method 的文档明确指出 Abort 可能会中止静态构造函数。
When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain.
和
For example, calling Thread.Abort may prevent static constructors from executing or prevent the release of unmanaged resources.
虽然您的示例优雅地表明静态构造函数可能不会被中断,但不能保证这种行为。
更新
这是一个静态构造函数被 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
看来静态构造函数保证已经完成,差不多了。
可以使用 RuntimeHelpers.RunClassConstructor
显式调用静态构造函数,其中'确保指定类型的类型初始值设定项(也称为静态构造函数)已 运行'.
在你的例子中,代码可以这样写。
var t = new Thread(() =>
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(MyCls).TypeHandle);
var m = new MyCls();
});
RunClassConstructor
调用 _RunClassConstructor
并用以下注释进行注释。
In the absence of class constructor deadlock conditions, the call is further guaranteed to have completed.
// 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);
我正在测试以下代码:
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..");
}
}
我得到的输出是:
0123456789
Done
似乎 t.Abort()
调用阻塞了主线程,直到静态构造函数的执行完成,并且根据 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.
我的问题是:
- 静态构造函数真的 运行 作为受限执行区域 (CER) 吗?
- 如果是,还有哪些其他代码阻止 运行 作为 CER?
更新:问题是关于 t.Abort()
阻塞,而不是中断,所以这个答案几乎不相关:)
Thread.Abort Method 的文档明确指出 Abort 可能会中止静态构造函数。
When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain.
和
For example, calling Thread.Abort may prevent static constructors from executing or prevent the release of unmanaged resources.
虽然您的示例优雅地表明静态构造函数可能不会被中断,但不能保证这种行为。
更新
这是一个静态构造函数被 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
看来静态构造函数保证已经完成,差不多了。
可以使用 RuntimeHelpers.RunClassConstructor
显式调用静态构造函数,其中'确保指定类型的类型初始值设定项(也称为静态构造函数)已 运行'.
在你的例子中,代码可以这样写。
var t = new Thread(() =>
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(MyCls).TypeHandle);
var m = new MyCls();
});
RunClassConstructor
调用 _RunClassConstructor
并用以下注释进行注释。
In the absence of class constructor deadlock conditions, the call is further guaranteed to have completed.
// 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);