簡體   English   中英

如何在C#中為Enum類型應用InterLocked.Exchange?

[英]How to apply InterLocked.Exchange for Enum Types in C#?

public enum MyEnum{Value1, Value2}  
class MyClass 
{ 
    private MyEnum _field;   
    public MyEnum Field  // added for convenience
    {
        get { return _field; }  
        set { Interlocked.Exchange(ref _field, value); // ERROR CS0452  }
    }  
} 

可以解決:

 public enum MyEnum{Value1, Value2}  
 public class MyClass2  
 {  
   private int _field;  //change to int
   public MyEnum Field  // added for convenience
   { 
    get { return (MyEnum)_field; }
    set { System.Threading.Interlocked.Exchange(ref _field, (int)value); }
   }  
 }

有沒有更好的方法來解決這個問題?

有沒有更好的方法來解決這個問題?

如果你需要使用Interlocked.Exchange那么這是最好的方法,事實上我認為這是交換枚舉的唯一方法。

您收到編譯器錯誤的原因是編譯器認為您要使用Exchange<T> ,但是T需要是一個引用類型,因為您沒有使用它失敗的引用類型。 因此,最好的解決方法是像你一樣強制轉換為int ,從而強制編譯器使用非泛型的Exchange(int, int)

您似乎不需要Interlocked.Exchange的“交換”功能,因為您忽略了它的返回值。 因此,我認為可能讓您最開心的解決方案是將_field標記為volatile:

private volatile MyEnum _field;

Interlocked方法很好。 你可以使用一個普通的舊lock ,但這似乎有點矯枉過正。 但是,您需要在getter中使用某種保護讀取,否則可能會遇到內存障礙問題。 由於您已經在setter中使用Interlocked方法,因此在getter中執行相同操作是有意義的。

public MyEnum Field  // added for convenience
{ 
  get { return (MyEnum)Interlocked.CompareExchange(ref _field, 0, 0); }
  set { Interlocked.Exchange(ref _field, (int)value); }
}  

如果你願意,你也可以將該字段標記為volatile

有沒有更好的方法來解決這個問題?

我使用的是一個類而不是枚舉:

public class DataCollectionManagerState
{
    public static readonly DataCollectionManagerState Off = new DataCollectionManagerState() { };
    public static readonly DataCollectionManagerState Starting = new DataCollectionManagerState() { };
    public static readonly DataCollectionManagerState On = new DataCollectionManagerState() { };

    private DataCollectionManagerState() { }

    public override string ToString()
    {
        if (this == Off) return "Off";
        if (this == Starting) return "Starting";
        if (this == On) return "On";

        throw new Exception();
    }
}

public class DataCollectionManager
{
    private static DataCollectionManagerState _state = DataCollectionManagerState.Off;

    public static void StartDataCollectionManager()
    {
        var originalValue = Interlocked.CompareExchange(ref _state, DataCollectionManagerState.Starting, DataCollectionManagerState.Off);
        if (originalValue != DataCollectionManagerState.Off)
        {
            throw new InvalidOperationException(string.Format("StartDataCollectionManager can be called when it's state is Off only. Current state is \"{0}\".", originalValue.ToString()));
        }

        // Start Data Collection Manager ...

        originalValue = Interlocked.CompareExchange(ref _state, DataCollectionManagerState.On, DataCollectionManagerState.Starting);
        if (originalValue != DataCollectionManagerState.Starting)
        {
            // Your code is really messy
            throw new Exception(string.Format("Unexpected error occurred. Current state is \"{0}\".", originalValue.ToString()));
        }
    }
}

為什么不簡單地同步線程?

protected static object _lockObj = new object();

set
{
    lock(_lockObj)
    {
         _field = value;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM