2012-06-27 10 views
10

Ich versuche SpinLock zu verwenden, aber auch diese grundlegendsten Code in einer Single-Threaded-Konsole app wirft die folgende Ausnahme, wenn ich callSpinLock.Exit()SpinLock werfen SynchronizationLockException

System.Threading.SynchronizationLockException was unhandled by user code 
    Message=The calling thread does not hold the lock. Source=mscorlib 

Hier ist die gesamte Quellcode. ..

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace ConsoleApplication48 
{ 
    class Program 
    { 
     static readonly SpinLock SpinLock = new SpinLock(); 
     static void Main(string[] args) 
     { 
      bool lockTaken = false; 
      try 
      { 
       SpinLock.Enter(ref lockTaken); 
       if (lockTaken) 
        Console.WriteLine("Lock taken"); 
      } 
      finally 
      { 
       if (lockTaken) 
        SpinLock.Exit(); 
      } 
      Console.WriteLine("Done"); 
     } 
    } 
} 
+0

Die Nachricht sagt, dass die Sperre nicht im Besitz desselben Threads ist, der Exit aufruft - aber aus dem Code ist es eindeutig. –

Antwort

14

SpinLock ist eine Struktur, und Sie lesen es aus einem Readonly-Feld. Die C# -Spezifikation besagt, dass in diesem Fall, um eine potentiell mutierende Funktion aufzurufen, die Struktur in eine veränderbare lokale Variable kopiert werden muss. Dies geschieht unter den Deckeln.

Ihre Anrufe auf Enter und Exit geschehen auf einer neuen Kopie Ihres Schlosses. Aus diesem Grund arbeitet Enter mit einer entsperrten Sperre.

Machen Sie die SpinLock-Variable nicht schreibgeschützt, weil sie mutiert ist.

+0

Ah, die Verwendung von "readonly" mit einem Werttyp gibt nicht nur an, dass das Feld nicht zuweisbar ist, sondern impliziert auch, dass der Wert unveränderlich ist, und um sicherzustellen, dass er den Wert beim Lesen kopiert. Danke –