43

以下代码

using System.Threading;

class Test
{
    volatile int counter = 0;
    public void Increment()
    {
        Interlocked.Increment(ref counter);
    }
}

引发以下编译器警告:

"A reference to a volatile field will not be treated as volatile"

我在这里做错了什么来发出这个警告吗?为什么编译器会对此发出警告?

4

4 回答 4

46

你没有做错任何事。根据文档

volatile 字段通常不应使用 ref 或 out 参数传递,因为在函数范围内它不会被视为 volatile。这也有例外,例如在调用互锁 API 时。

于 2009-01-08T17:29:20.837 回答
34

基本上警告是,当您通过引用传递 volatile 字段时,调用代码不知道以 volatile 方式处理它。对于 Interlocked.Increment,由于方法的性质,这可能无关紧要 - 但是如果您使用 Interlocked ,则无论如何您都不需要变量是 volatile。

一般来说,我想我会避免将两者混为一谈——如果你使用的是 Interlocked,那就到处做(Interlocked.CompareExchange(ref counter, 0, 0)用来阅读)。就个人而言,我不能说我经常使用 volatile。对于简单的计数器,我可能会使用互锁,但我更有可能对大多数任务使用锁。

于 2009-01-08T17:28:47.077 回答
31

用这个:

#pragma warning disable 420
if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
    return;
#pragma warning restore 420
于 2009-10-02T22:28:28.473 回答
3

您收到错误是因为您通过引用传递了该字段。我认为这意味着目标方法不知道该字段被标记为volatile,因此不会这样对待它。

于 2009-01-08T17:28:09.950 回答