什么可能导致以下异常?
System.MissingMethodException Int32 System.Environment.get_CurrentManagedThreadId()
此方法调用似乎是由C#编译器为生成IEnumerable<>
的方法生成的。
安装了.NET Framework v4.0 x86,并为v4.0 Any CPU编译了二进制文件。
答案 0 :(得分:53)
CurrentManagedThreadId
是.NET 4.5属性,因此您需要4.5才能运行代码。
有关此问题可能发生的分析,请参阅Iterator blocks, missing methods, and .NET 4.5。
简而言之:
如果在安装了.NET 4.5的系统上构建应用程序(针对.NET 4.0),它将使用4.5作为编译的基础,因为.NET 4.0始终被.NET 4.5覆盖。
如果您的应用程序也使用yield return
,它将在仅安装4.0的系统上失败,因为此语句的实现在为4.5 Framework编译时使用新属性。
要解决此问题,请确保您的编译器系统具有4.0参考程序集。
答案 1 :(得分:3)
借调 floele 的回答;有关更多上下文,这里是对问题的简要分析:
当编译器处理返回IEnumerable
的迭代器块时,它会生成一个私有IEnumerable
类来保存迭代逻辑。这是4.0编译器为其GetEnumerator
方法生成IL的开始:
.method private final hidebysig newslot virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 'System.Collections.Generic.IEnumerable<System.String>.GetEnumerator' () cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
01 00 00 00
)
.override method instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator()
// Method begins at RVA 0x57848
// Code size 89 (0x59)
.maxstack 6
.locals init (
[0] bool,
[1] class DOT.Core.MiscHelpers/'<ReadLines>d__0',
[2] class [mscorlib]System.Collections.Generic.IEnumerator`1<string>
)
IL_0000: call class [mscorlib]System.Threading.Thread [mscorlib]System.Threading.Thread::get_CurrentThread()
IL_0005: callvirt instance int32 [mscorlib]System.Threading.Thread::get_ManagedThreadId()
IL_000a: ldarg.0
IL_000b: ldfld int32 DOT.Core.MiscHelpers/'<ReadLines>d__0'::'<>l__initialThreadId'
IL_0010: bne.un IL_0027
请注意对System.Threading.Thread::get_CurrentThread()
和System.Threading.Thread::get_ManagedThreadId();
的来电。生成的方法使用它来执行优化,如果立即消耗IEnumerable
[1],则返回相同的对象实例(节省构造函数调用的成本)。
以下是4.5编译器生成的IL:
.method private final hidebysig newslot virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 'System.Collections.Generic.IEnumerable<System.String>.GetEnumerator' () cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
01 00 00 00
)
.override method instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator()
// Method begins at RVA 0x4830c
// Code size 64 (0x40)
.maxstack 2
.locals init (
[0] class DOT.Core.MiscHelpers/'<ReadLines>d__0'
)
IL_0000: call int32 [mscorlib]System.Environment::get_CurrentManagedThreadId()
IL_0005: ldarg.0
IL_0006: ldfld int32 DOT.Core.MiscHelpers/'<ReadLines>d__0'::'<>l__initialThreadId'
IL_000b: bne.un IL_002b
请注意,前一个方法的两个调用现在被System.Environment::get_CurrentManagedThreadId()
替换,table.dataTable thead .sorting::after,
table.dataTable thead .sorting_asc::after {
display:none;
}
table.dataTable thead .sorting_desc::after {
display:none;
}
table.dataTable thead .sorting {
background-image: url(https://datatables.net/media/images/sort_both.png);
background-repeat: no-repeat;
background-position: center right;
}
table.dataTable thead .sorting_asc {
background-image: url(https://datatables.net/media/images/sort_asc.png);
background-repeat: no-repeat;
background-position: center right;
}
table.dataTable thead .sorting_desc {
background-image: url(https://datatables.net/media/images/sort_desc.png);
background-repeat: no-repeat;
background-position: center right;
}
是.NET 4.5中添加的属性。
由于4.5升级会覆盖4.0 C#编译器(csc.exe),因此在您的计算机上为4.0编译的代码将使用新的IL模板,并且不会在vanilla 4.0安装上运行,除非您拥有.NET 4.0参考组件[2],这将导致编译器生成旧版本的IL。
[1]也就是说,第一次在创建它的线程上消耗它(例如在foreach语句中)。
[2]实际上可以从.NET Framework安装程序中提取.NET 4.0编译器,并修改项目文件以使用它编译代码。这可能是另一种解决问题的方法,但这是一个很长的故事,我不会在这里详述