Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在不安全区域禁止等待?_C#_Unsafe_Async Await - Fatal编程技术网

C# 为什么在不安全区域禁止等待?

C# 为什么在不安全区域禁止等待?,c#,unsafe,async-await,C#,Unsafe,Async Await,根据,在不安全的块中禁止使用wait关键字,只提到“保存非托管指针固有的困难”。对于这些困难有什么好的解释吗?您需要知道的两件基本事情。异步方法被C#编译器重写为一个小类,该类具有一个无法描述的名称,它封装了一个状态机。异步方法的局部变量成为该类的字段 不安全代码通常依赖于能够创建指向局部变量的指针。fixed语句是这样的,它创建了一个隐藏的局部变量,垃圾收集器可以看到该变量,从而在垃圾收集发生时进行更新,从而移动正在修复的数组。创建指向局部变量的指针很好,这些变量不会被垃圾收集器移动。线程堆栈

根据,在
不安全的
块中禁止使用
wait
关键字,只提到“保存非托管指针固有的困难”。对于这些困难有什么好的解释吗?

您需要知道的两件基本事情。异步方法被C#编译器重写为一个小类,该类具有一个无法描述的名称,它封装了一个状态机。异步方法的局部变量成为该类的字段

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

将两者连接起来,您就会看到问题所在,一个局部变量可以变成一个类的字段,当垃圾回收发生时,这个字段的地址会发生变化。突然将不安全代码变成破坏代码

演示此问题的代码段:

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

C#团队本可以努力仔细分析不安全代码在重写后仍然正常的情况。但有些情况是不可修复的,比如固定语句。为了给程序员带来令人失望的消息而做的大量工作,通常是出于令人困惑的原因。在这里,明智的做法是简单地宣布不安全代码禁止使用。

您还想了解更多详细信息吗?“你不能在不安全的区块中使用它。”米奇麦,我承认我在这里抓住了,但也许OP正在寻找关于这意味着什么的信息。这意味着你不能在那里使用它!即使有详细的解释,你仍然无法在那里使用它。也许OP应该解释他们试图解决的问题。@MitchWheat:有时候人们只是想学习something@MitchWheat,StackOverflow中有很多答案都详细阐述了这样的细节。事实上,它可能不会改变我是否可以在一个不安全的块中使用wait,但是关于为什么我不能使用wait的见解可能会帮助我选择适合我希望的时间的模式。这是很有意义的。遗憾的是,相关的状态机不能简单地被声明为
固定的
(我认为是可选的)并用它来完成。我猜解决方案是显式地将需要的闭包变量分配到一个类中,修复该类,并适当地引用它的各个部分。但这就放弃了异步重写器的一半好处。真可惜!