【问题标题】:Why is await forbidden in unsafe sections?为什么在不安全的部分禁止等待?
【发布时间】:2013-03-04 03:33:06
【问题描述】:

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

【问题讨论】:

  • 您还需要什么详细信息?你不能在不安全的区块中使用它。
  • @MitchWheat 我承认我在这里掌握,但也许 OP 正在寻找有关 含义 的信息。
  • 这意味着你不能在那里使用它!即使有详细的解释,您仍然无法在那里使用它。也许 OP 应该解释他们试图解决的问题。
  • @MitchWheat:有时人们只是想学习一些东西
  • @MitchWheat,StackOverflow 充满了详细说明此类细节的答案。实际上,我是否可以在不安全的块中使用 await 可能不会改变,但是关于我为什么不能使用的见解可能有助于在我希望可以的时候选择模式。

标签: c# unsafe async-await


【解决方案1】:

您需要了解的两个基本知识。一个异步方法被 C# 编译器重写为一个包含状态机的名称难以描述的小类。异步方法的局部变量成为该类的字段。

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

将两者联系起来,你就会发现问题所在,一个局部变量可以变成一个类的字段,当垃圾回收发生时,该字段的地址确实会改变。突然把不安全的代码变成了破坏代码。

演示问题的代码 sn-p:

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

C# 团队可以努力仔细分析不安全代码在重写后仍然可以使用的情况。但是有些情况是无法修复的,例如 fixed 语句。一堆工作只会给程序员带来令人失望的消息,通常是出于令人困惑的原因。明智的做法是简单地将不安全代码声明为禁区。

【讨论】:

  • 这很有道理。遗憾的是,相关状态机不能简单地声明为fixed(我想是可选的)并完成它。我想解决方案是将您需要的闭包变量显式分配到一个类中,修复该类,并适当地引用它的一部分。但这放弃了异步重写器魔法的一半好处。太可惜了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-12
  • 2022-01-21
  • 2021-05-29
  • 2021-08-02
  • 1970-01-01
相关资源
最近更新 更多