为什么在不安全的部分等待被禁止?

时间:2013-03-03 03:35:42

标签: c# unsafe async-await

根据http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspxawait块中禁止使用unsafe关键字,仅提及“保留非托管指针所固有的困难”。对这些困难有什么好的解释吗?

1 个答案:

答案 0 :(得分:8)

您需要了解的两件基本事项。异步方法被C#编译器重写为一个小类,其中包含一个包装状态机的无法形容的名称。 async方法的局部变量成为该类的字段。

不安全的代码通常依赖于能够创建指向局部变量的指针。 fixed 语句就是这样,它创建了一个隐藏的局部变量,垃圾收集器可以看到它,从而在发生垃圾收集时更新,从而移动正在修复的数组。创建指向局部变量的指针很好,这些变量不会被垃圾收集器移动。线程堆栈始终位于虚拟内存地址空间中的固定位置。

连接这两个,你看到问题,一个局部变量可以变成一个类的字段,一个字段在发生垃圾收集时发生变化。突然把不安全的代码变成破坏代码。

演示此问题的代码段:

class Example {
    int field;
    unsafe void Method() {
        int local = 42;
        int* p = &local;   // fine
        int* q = &field;   // CS0212
    }
}

C#团队可以努力仔细分析重写后不安全代码仍然可以的情况。但是有些情况只是不可修复,比如 fixed 语句。一堆工作只给程序员带来令人失望的消息,通常是因为一个令人困惑的原因。这里理智的做法是简单地宣布不安全的代码不受限制。