如何应用InterLocked.在c#中交换枚举类型
本文关键字:交换 枚举 类型 InterLocked 何应用 应用 | 更新日期: 2023-09-27 18:06:28
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的"交换"功能。因为您忽略了它的返回值。因此,我认为最让您满意的解决方案是将_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
。
对于这个问题有没有更好的方法?
我使用类代替Enum:
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;
}
}