System.MissingMethodException Int32 System.Environment。 get_CurrentManagedThreadId()

时间:2013-03-22 11:53:37

标签: c# .net-4.0

什么可能导致以下异常?

System.MissingMethodException Int32 System.Environment.get_CurrentManagedThreadId()

此方法调用似乎是由C#编译器为生成IEnumerable<>的方法生成的。

安装了.NET Framework v4.0 x86,并为v4.0 Any CPU编译了二进制文件。

2 个答案:

答案 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编译器,并修改项目文件以使用它编译代码。这可能是另一种解决问题的方法,但这是一个很长的故事,我不会在这里详述