44 Stimmen

"Ein Verweis auf ein flüchtiges Feld wird nicht als flüchtig behandelt.

Der folgende Code

using System.Threading;

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

Gibt die folgende Compiler-Warnung aus:

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

Mache ich hier etwas falsch, um diese Warnung auszulösen? Warum warnt mich der Compiler vor diesem Problem?

47voto

Darin Dimitrov Punkte 990883

Sie machen nichts falsch. Laut der Dokumentation :

Ein flüchtiges Feld sollte normalerweise nicht mit einem ref oder out Parameter übergeben werden, da es nicht innerhalb des Bereichs nicht als flüchtig behandelt wird der Funktion behandelt wird. Es gibt Ausnahmen Ausnahmen, zum Beispiel beim Aufruf einer verriegelten API.

20 Stimmen

Ich würde sagen, dass die Interlocked-Methoden es immer noch nicht anders behandeln als jedes andere Feld - es ist nur so, dass alle Felder werden von Interlocked auf besondere Weise behandelt.

3 Stimmen

Einverstanden. Volatile ist für die Interlocked API irrelevant. Aber in bestimmten Fällen ist es sehr nützlich, Interlocked und Volatile zu mischen.

0 Stimmen

Ich bin zwar etwas spät dran, aber @IamIC: Könnten Sie uns sagen, welche Fälle das sein könnten?

35voto

Jon Skeet Punkte 1325502

Die Warnung besteht im Wesentlichen darin, dass der aufrufende Code nicht weiß, wie er ein flüchtiges Feld behandeln soll, wenn er es per Referenz übergibt. Bei Interlocked.Increment spielt das aufgrund der Art der Methode wahrscheinlich keine Rolle - aber dann muss die Variable nicht flüchtig sein trotzdem wenn Sie Interlocked verwenden.

Im Allgemeinen würde ich es vermeiden, die beiden zu mischen - wenn Sie Interlocked verwenden, tun Sie es überall (mit Interlocked.CompareExchange(ref counter, 0, 0) um sie zu lesen). Ich kann nicht sagen, dass ich persönlich sehr oft volatile verwende. Für einfache Zähler ich könnte Interlocked verwenden, aber für die meisten Aufgaben verwende ich eher ein Schloss.

0 Stimmen

Sie bringen mich durcheinander. In einer früheren Frage (395232) habe ich Ihrer Antwort entnommen, dass ich sowohl Interlocked als auch Volatile benötige. Jetzt sagen Sie: "Sie brauchen die Variable sowieso nicht flüchtig zu machen, wenn Sie Interlocked verwenden".

0 Stimmen

Nein, sie sind Alternativen zueinander: "Oder verwenden Sie lieber Interlocked, eine flüchtige Variable oder eine Sperre." Das sollte drei Möglichkeiten bieten verschiedene Ansätze, nicht einen kombinierten. War das der Teil, der Sie in die Irre geführt hat?

0 Stimmen

Ich weiß, dass in einer Multiprozessor-Umgebung mehrere Caches dazu führen können, dass ein Prozessor einen Cache-Wert inkrementiert, der nicht der letzte Wert ist. In diesem Fall hilft, soweit ich weiß, ein Interlocked nicht, weil es nicht die MemoryBarrier schafft, die zur Aktualisierung der Caches benötigt wird.

31voto

Robert Fraser Punkte 10267

Verwenden Sie dies:

#pragma warning disable 420
if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
    return;
#pragma warning restore 420

4 Stimmen

Sie ist jedoch nützlich, wenn Sie die anderen Antworten verstanden haben, falls Sie sich dafür entscheiden, sowohl Interlocked als auch Volatile zu verwenden.

5 Stimmen

@JaderDias -- Nein, aber er sagt Ihnen, was Sie wegen der Warnung tun sollen. Was super nützlich ist. -- Außerdem war das Artwork auch irgendwie lustig.

0 Stimmen

@RyanM das Kunstwerk war lustig. Warum haben Sie es entfernt? Diese Antwort sieht ohne sie nackt aus!

3voto

Kent Boogaart Punkte 170094

Sie erhalten die Fehlermeldung, weil Sie das Feld als Referenz übergeben. Ich denke, das bedeutet, dass die Zielmethode keine Ahnung hat, dass das Feld als volatile und wird daher nicht als solche behandelt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X