Общее перечисление между несколькими потоками

У меня есть перечисление, которое используется несколькими потоками:

public enum Action
{
   Read,
   Write,
   None
}

Внутри класса у меня есть переменная типа Action:

public Action _action;

Это общая переменная, то есть она обновляется и читается из нескольких потоков.

Например, из одного потока я делаю:

_action = Action.Read

И из другого:

if (_action == Action.Read)
{
}
else if (_action == Action.Write)
{
}
else if (_Action == Action.None)
{
}
else
{
}

Поэтому я хотел бы использовать Interlock для обновления и/или чтения из разных потоков одновременно. Как я могу сделать это через свойство?

Я видел много сообщений, например ниже:

Как применить InterLocked.Exchange для типов Enum в C#?

Проблема здесь в том, что перечисление должно быть приведено к типу int, но я хотел бы сохранить перечисление без приведения. Является ли это возможным? Если да, не могли бы вы опубликовать какой-нибудь пример? Также возможно ли совместить volatile с блокировкой? Я имею в виду применение блокировки к изменчивому перечислению.


person Ralph    schedule 22.05.2017    source источник
comment
Этот и связанный вопрос задают одно и то же: я знаю, как решить эту проблему с помощью кастинга. Могу ли я решить это без кастинга? Я не думаю, что ответ «Нет, действительно, я не хочу использовать приведение» делает эти ответы недействительными или делает их не дубликатами. Вы можете попробовать адаптировать некоторые ответы на близкий к, если не точный, дубликат вопроса Interlocked.CompareExchange with enum, но я думаю, вы обнаружите, что эти решения не красивее/чище/желательнее, чем кастинг. Действительно.   -  person Lance U. Matthews    schedule 23.05.2017


Ответы (1)


В этом случае Interlocked бесполезен. Ваша серия проверок if/then зависит от значения _action, остающегося неизменным при их выполнении. В противном случае _action==Action.Read может быть ложным, но перед выполнением следующего оператора _action устанавливается в Action.Read, а все остальные условия ложны.

Вы хотели бы использовать lock, чтобы гарантировать, что ничто не изменяет _action во время выполнения этих операторов.

Итак, у вас может быть объект для вашего замка:

private readonly _lockObject = new object();

И затем, когда _action устанавливается:

lock(_lockObject)
{
    _action = newValue;
}

И при выполнении ваших условий вы можете просто прочитать значение _action в lock, а затем отпустить его. Таким образом, замок удерживается в течение минимально возможного времени. Если _action изменится, пока вы выполняете свои условия, это не повлияет на вас, потому что вы создали отдельное значение и больше не зависите от значения _action.

Action action;
lock(_lockObject)
{
    action = _action
}
if (action == Action.Read)
{
}
else if (action == Action.Write)
{
}
else if (action == Action.None)
{
}
else
{
}
person Scott Hannen    schedule 23.05.2017
comment
И это хорошая идея сделать переменную _action volatile в сочетании с блокировкой? например общедоступное изменчивое действие _action - person Ralph; 23.05.2017