Обработка условий состязания в C#

Я пишу приложение с многоуровневым интерфейсом связи.
Это было сделано, чтобы абстрагировать связь от части пользовательского интерфейса приложения и также сделать это более масштабируемым/удобным в сопровождении.
Например:

alt text

Рассмотрите каждое поле в числе выше как отдельный класс.
Универсальный Интерфейс Comms заполняет строковые переменные, описывающие проведенные данные и comms "здоровье", которые в свою очередь копируются до Приложения через серию вызовов государственной функции. Например, Приложение позвонило бы App-Sub-System:

class Application
{
   private void SomeUpdateFunction()
   {
      this.textBox1.AppendText(this.AppSubSystem.GetText());
   }
}

class AppSubSystem
{
   public string GetText()
   {
      return this.GenericCommsInterface.GetText();
   }
}

class GenericCommsInterface
{
   public string GetText()
   {
      string sRetVal = this.sText; // sText is populated by other functions in the class.
      this.sText = null; // Suspected race condition is here.
      return sRetVal;
   }
}

sText заполняется асинхронно другими функциями в классе.
Я живо состояние состязания происхожу между string sRetVal = this.sText; и следующая строка this.sText = null;.
Кто-то может предложить способ избежать или предотвратить это состояние состязания? Был бы с помощью StringBuilder справка, или там иначе, что я должен делать это?

8
задан Hakan Fıstık 18 July 2017 в 12:59
поделиться

3 ответа

Вероятно, вы должны получить блокировку каждый раз, когда захотите коснуться this.sText - в функциях, которые его обновляют, а также в вашем GetText функция. Это гарантирует, что только один поток за раз возится с ним, поскольку (при условии, что ваш поток имеет блокировку) другие потоки будут сидеть и ждать, пока текущий поток не будет завершен.

Я бы порекомендовал вам использовать StringBuilder, отчасти для упрощения блокировки, поскольку блокировка строки, которая оказалась интернированной или отключенной в середине заблокированной операции (и, таким образом, разблокированной с точки зрения постороннего), может вызвать очень плохое моджо. Что-то вроде этого может помочь:

lock (this.sbText)
{
    sRetVal = this.sbText.ToString();
    this.sbText.Length = 0;
}

В качестве альтернативы вы можете заблокировать этот , но это некрасиво - ваши блокировки должны быть внутри, как можно более приватными, чтобы избежать странных побочных эффектов (например, если некоторые другой объект пытался получить блокировку этого объекта - он не мог этого сделать, пока sbText изменялся).

4
ответ дан 5 December 2019 в 22:16
поделиться
public string GetText()
{
   lock( someObject )
   {
      string sRetVal = this.sText; // sText is populated by other functions in the class.
      this.sText = null; // Suspected race condition is here.
      return sRetVal;
   }
}    

в вашем наборе

lock( someObject )
{
    //...
    this.sText = value;
}
1
ответ дан 5 December 2019 в 22:16
поделиться

Этот код наверняка не будет работать в многопоточной среде, поскольку вы не защищаете sText. Вам нужно заблокировать всех, кто имеет к нему доступ.

1
ответ дан 5 December 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: